diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..010ec9d --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,14 @@ +[profile.release] +opt-level = 'z' +lto = true +codegen-units = 1 + +[unstable] +build-std = ["core", "alloc"] +build-std-features = ["compiler-builtins-mem"] + +# By default, heap size is enforced to 8192 bytes. +# Authorized values are [2048, 4096, 8192, 16384, 24576] +# We use 16k as we get some crashes on 8k when running the tests with big 20+ input TXs +[env] +HEAP_SIZE = "16384" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5462dbb --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "cargo" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" + allow: + - dependency-name: "ledger_device_sdk" + - dependency-name: "include_gif" diff --git a/.github/workflows/build_and_functional_tests.yml b/.github/workflows/build_and_functional_tests.yml new file mode 100644 index 0000000..3e87c18 --- /dev/null +++ b/.github/workflows/build_and_functional_tests.yml @@ -0,0 +1,49 @@ +name: Build and run functional tests using ragger through reusable workflow + +# This workflow will build the app and then run functional tests using the Ragger framework upon Speculos emulation. +# It calls a reusable workflow developed by Ledger's internal developer team to build the application and upload the +# resulting binaries. +# It then calls another reusable workflow to run the Ragger tests on the compiled application binary. +# +# The build part of this workflow is mandatory, this ensures that the app will be deployable in the Ledger App Store. +# While the test part of this workflow is optional, having functional testing on your application is mandatory and this workflow and +# tooling environment is meant to be easy to use and adapt after forking your application + +permissions: + actions: write + contents: write + pull-requests: write + +on: + workflow_dispatch: + inputs: + golden_run: + type: choice + required: true + default: 'Raise an error (default)' + description: CI behavior if the test snaphots are different than expected. + options: + - 'Raise an error (default)' + - 'Open a PR' + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + build_application: + name: Build application using the reusable workflow + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_build.yml@v1 + with: + upload_app_binaries_artifact: "compiled_app_binaries" + builder: ledger-app-builder + + ragger_tests: + name: Run ragger tests using the reusable workflow + needs: build_application + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_ragger_tests.yml@v1 + with: + download_app_binaries_artifact: "compiled_app_binaries" + regenerate_snapshots: ${{ inputs.golden_run == 'Open a PR' }} diff --git a/.github/workflows/coding_style_checks.yml b/.github/workflows/coding_style_checks.yml new file mode 100644 index 0000000..7f91930 --- /dev/null +++ b/.github/workflows/coding_style_checks.yml @@ -0,0 +1,21 @@ +name: Run coding style check + +# This workflow will run linting checks to ensure a level of code quality among all Ledger applications. +# +# The presence of this workflow is mandatory as a minimal level of linting is required. + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + check_linting: + name: Check linting using the reusable workflow + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_lint.yml@v1 + with: + source: './src' diff --git a/.github/workflows/extra_checks.yml b/.github/workflows/extra_checks.yml new file mode 100644 index 0000000..b90d19f --- /dev/null +++ b/.github/workflows/extra_checks.yml @@ -0,0 +1,28 @@ +name: Run extra checks + +# This workflow will run `run_extra_checks.sh` from the project root. + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + run_extra_checks: + runs-on: ubuntu-24.04 + steps: + - name: Checkout the repository + uses: actions/checkout@v5 + + # Note: no need to install docker manually, because it's already installed, see + # https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md + + - name: Run the checks + run: | + docker run --rm -v "$(realpath .):/app" -w /app \ + ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest \ + bash run_extra_checks.sh diff --git a/.github/workflows/guidelines_enforcer.yml b/.github/workflows/guidelines_enforcer.yml new file mode 100644 index 0000000..b217d84 --- /dev/null +++ b/.github/workflows/guidelines_enforcer.yml @@ -0,0 +1,27 @@ +name: Ensure compliance with Ledger guidelines + +# This workflow is mandatory in all applications +# It calls a reusable workflow guidelines_enforcer developed by Ledger's internal developer team. +# The successful completion of the reusable workflow is a mandatory step for an app to be available on the Ledger +# application store. +# +# More information on the guidelines can be found in the repository: +# LedgerHQ/ledger-app-workflows/ + +permissions: + actions: write + contents: read + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + guidelines_enforcer: + name: Call Ledger guidelines_enforcer + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_guidelines_enforcer.yml@v1 diff --git a/.github/workflows/misspellings_checks.yml b/.github/workflows/misspellings_checks.yml new file mode 100644 index 0000000..845be36 --- /dev/null +++ b/.github/workflows/misspellings_checks.yml @@ -0,0 +1,19 @@ +name: Misspellings checks + +# This workflow performs some misspelling checks on the repository +# It is there to help us maintain a level of quality in our codebase and does not have to be kept on forked +# applications. + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + misspell: + name: Check misspellings + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_spell_check.yml@v1 diff --git a/.github/workflows/python_tests_checks.yml b/.github/workflows/python_tests_checks.yml new file mode 100644 index 0000000..f035629 --- /dev/null +++ b/.github/workflows/python_tests_checks.yml @@ -0,0 +1,44 @@ +name: Checks on the Python tests + +# This workflow performs some checks on the Python client used by the Boilerplate tests +# It is there to help us maintain a level of quality in our codebase and does not have to be kept on forked +# applications. + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + + lint: + name: Boilerplate client linting + runs-on: ubuntu-latest + steps: + - name: Clone + uses: actions/checkout@v3 + - name: Installing PIP dependencies + run: | + pip install pylint + pip install --extra-index-url https://test.pypi.org/simple/ -r tests/requirements.txt + - name: Lint Python code + run: | + pylint --rc tests/setup.cfg tests/application_client/ + + mypy: + name: Type checking + runs-on: ubuntu-latest + steps: + - name: Clone + uses: actions/checkout@v3 + - name: Installing PIP dependencies + run: | + pip install mypy + pip install --extra-index-url https://test.pypi.org/simple/ -r tests/requirements.txt + - name: Mypy type checking + run: | + mypy tests/application_client/ diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 0000000..fb70e1e --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,31 @@ +name: Run unit tests + +# This workflow will run `run_unit_tests.sh` from the project root for each device model. + +on: + workflow_dispatch: + push: + branches: + - master + - main + - develop + pull_request: + +jobs: + run_extra_checks: + runs-on: ubuntu-24.04 + strategy: + matrix: + model: [nanox, nanosp, stax, flex, apex_p] + steps: + - name: Checkout the repository + uses: actions/checkout@v5 + + # Note: no need to install docker manually, because it's already installed, see + # https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md + + - name: Run the checks + run: | + docker run --rm -v "$(realpath .):/app" -w /app \ + ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest \ + bash run_unit_tests.sh ${{ matrix.model }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..246e261 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +target +app.json +app_nanos.json +app_nanosplus.json +app_nanox.json +app_stax.json +app_flex.json + +# Temporary directory with snapshots taken during test runs +tests/snapshots-tmp/ + +.DS_Store + +# Python +*.pyc[cod] +*.egg +__pycache__/ +*.egg-info/ +.eggs/ +.python-version + +# Related to the Ledger VSCode extension +# Virtual env for sideload (macOS and Windows) +ledger/ +# Build directory +build/ + +# VSCode +.vscode/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..4f1a245 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1647 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom 8.0.0", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.104", +] + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "bitstream-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" + +[[package]] +name = "built" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "cc" +version = "1.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "chrono" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +dependencies = [ + "num-traits", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "const-zero" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3c6565524986fe3225da0beb9b4aa55ebc73cd57ff8cb4ccf016ca4c8d006af" + +[[package]] +name = "const_format" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.104", + "unicode-xid", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "embedded-alloc" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddae17915accbac2cfbc64ea0ae6e3b330e6ea124ba108dada63646fd3c6f815" +dependencies = [ + "critical-section", + "linked_list_allocator", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fax" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "gif" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "image" +version = "0.25.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40fac9d56ed6437b198fddba683305e8e2d651aa42647f00f5ae542e7f5c94a2" + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "include_gif" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59152fb9707e856f65a10a25ba0b7141589bcf5cbe7f653fcda2875e45fc78f7" +dependencies = [ + "flate2", + "image", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + +[[package]] +name = "ledger_device_sdk" +version = "1.35.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85fc7dea35e2d9d0a305fc9594539af5f510cd7c2d764f944542c4710731ae58" +dependencies = [ + "const-zero", + "include_gif", + "ledger_secure_sdk_sys", + "num-traits", + "numtoa", + "rand_core", + "serde_json", + "zeroize", +] + +[[package]] +name = "ledger_secure_sdk_sys" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58d50b8764859daf1b5176c5aad8ccc989494c16b08fa266e22c7907e60956e9" +dependencies = [ + "bindgen", + "cc", + "critical-section", + "embedded-alloc", + "glob", +] + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "linked_list_allocator" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mintlayer-app" +version = "0.1.0" +dependencies = [ + "image", + "ledger_device_sdk", + "mintlayer-app-core", +] + +[[package]] +name = "mintlayer-app-core" +version = "0.1.0" +dependencies = [ + "bech32", + "chrono", + "hex", + "ledger_device_sdk", + "ledger_secure_sdk_sys", + "mintlayer-core-primitives", + "mintlayer-messages", + "testmacro", +] + +[[package]] +name = "mintlayer-core-primitives" +version = "1.0.0" +source = "git+https://github.com/mintlayer/mintlayer-core-primitives?rev=8644bfe06d932d687075939d2d175183ba1c369d#8644bfe06d932d687075939d2d175183ba1c369d" +dependencies = [ + "derive_more", + "fixed-hash", + "parity-scale-codec", + "strum", +] + +[[package]] +name = "mintlayer-messages" +version = "0.1.0" +dependencies = [ + "derive_more", + "mintlayer-core-primitives", + "num_enum", + "parity-scale-codec", +] + +[[package]] +name = "moxcms" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c588e11a3082784af229e23e8e4ecf5bcc6fbe4f69101e0421ce8d79da7f0b40" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "numtoa" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f" + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "git+https://github.com/paritytech/parity-scale-codec.git?rev=5021525697edc0661591ebc71392c48d950a10b0#5021525697edc0661591ebc71392c48d950a10b0" +dependencies = [ + "arrayvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "git+https://github.com/paritytech/parity-scale-codec.git?rev=5021525697edc0661591ebc71392c48d950a10b0#5021525697edc0661591ebc71392c48d950a10b0" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "png" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" +dependencies = [ + "proc-macro2", + "syn 2.0.104", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" +dependencies = [ + "quote", + "syn 2.0.104", +] + +[[package]] +name = "pxfm" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cbdf373972bf78df4d3b518d07003938e2c7d1fb5891e55f9cb6df57009d84" +dependencies = [ + "num-traits", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "testmacro" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e81321e8c082256753e5af547c7352ff5a9f1958c4c7e7de1eb8289ce65884f2" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "tiff" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.104", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "weezl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "zerocopy" +version = "0.8.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bce33a6288fa3f072a8c2c7d0f2fdbb90e28298f0135c1f99b96c3db2efcc60b" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd425244944f4ab65ccff928e7323354c5a018c75838362fdce749dfad2ee1e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zmij" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445" + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6343154 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,83 @@ +[package] +name = "mintlayer-app" +version.workspace = true +edition = "2021" + +[workspace] +members = ["crates/app-core", "crates/messages"] +resolver = "2" + +[workspace.package] +version = "0.1.0" + +[workspace.dependencies] +bech32 = { version = "0.11", default-features = false } +chrono = { version = "0.4", default-features = false } +derive_more = { version = "2.1.1", default-features = false } +hex = { version = "0.4.3", default-features = false } +image = "0.25.8" +ledger_device_sdk = "1.35.1" +ledger_secure_sdk_sys = "1.16.1" +num_enum = { version = "0.7.5", default-features = false } +# Note: the testmacro crate is published by Ledger and its source code comes from the `testmacro` +# dir inside the sdk repo, i.e. https://github.com/LedgerHQ/ledger-device-rust-sdk/tree/cad196841dbd72c037cfa01bec81a4a3ae57a04e/testmacro +# (though the published version is a bit older). +testmacro = "0.1.0" + +mintlayer-app-core = { path = "crates/app-core" } +mintlayer-messages = { path = "crates/messages" } + +[workspace.dependencies.parity-scale-codec] +git = "https://github.com/paritytech/parity-scale-codec.git" +# Use the specific commit "5021525697edc0661591ebc71392c48d950a10b0", +# which includes a fix for NanoX devices that do not support certain +# atomic operations. +# +# Fix reference: https://github.com/paritytech/parity-scale-codec/pull/751 +# This fix should be included in releases after version 3.7.5. +rev = "5021525697edc0661591ebc71392c48d950a10b0" +default-features = false + +[workspace.dependencies.mintlayer-core-primitives] +git = "https://github.com/mintlayer/mintlayer-core-primitives" +# The commit "Merge pull request #4 from mintlayer/fix_typo". +rev = "8644bfe06d932d687075939d2d175183ba1c369d" +package = "mintlayer-core-primitives" + +[dependencies] +ledger_device_sdk.workspace = true + +mintlayer-app-core.workspace = true + +[build-dependencies] +image.workspace = true + +[[bin]] +# Note: we only have this section to disable tests, but Cargo inists that "name" should also +# be specified. +name = "mintlayer-app" +# The app bin crate is a thin wrapper around `mintlayer-app-core` and it's not supposed to have +# unit tests of its own. So we disable tests completely to prevent Cargo from producing an uncompilable +# test binary. +test = false + +[package.metadata.ledger] +curve = ["secp256k1"] +flags = "0" +path = ["44'/19788'", "44'/1'"] +name = "Mintlayer" + +[package.metadata.ledger.nanox] +icon = "icons/mintlayer_14x14.gif" + +[package.metadata.ledger.nanosplus] +icon = "icons/mintlayer_14x14.gif" + +[package.metadata.ledger.stax] +icon = "icons/mintlayer_32x32.gif" + +[package.metadata.ledger.flex] +icon = "icons/mintlayer_40x40.gif" + +[package.metadata.ledger.apex_p] +icon = "icons/mintlayer_32x32.png" diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 65bdee8..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Mintlayer - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..326d124 --- /dev/null +++ b/README.md @@ -0,0 +1,149 @@ +# Ledger Rust Mintlayer Application + +![Rule enforcer](https://github.com/mintlayer/mintlayer-ledger-app/actions/workflows/guidelines_enforcer.yml/badge.svg) ![Build and tests](https://github.com/mintlayer/mintlayer-ledger-app/actions/workflows/build_and_functional_tests.yml/badge.svg) + +This is the Mintlayer Ledger application for the Ledger Nano X, S+, Stax, Flex and Nano Gen 5 devices. + +:warning: Nano S is not supported + +## Quick start guide + +### With VS Code + +You can quickly setup a development environment on any platform (macOS, Linux or Windows) to build and test your application with [Ledger's VS Code extension](https://marketplace.visualstudio.com/items?itemName=LedgerHQ.ledger-dev-tools). + +By using Ledger's own developer tools [Docker image](https://github.com/LedgerHQ/ledger-app-builder/pkgs/container/ledger-app-builder%2Fledger-app-dev-tools), the extension allows you to **build** your apps with the latest SDK, **test** them on **Speculos** and **load** them on any supported device. + +- Install and run [Docker](https://www.docker.com/products/docker-desktop/). +- Make sure you have an X11 server running : + - On Ubuntu Linux, it should be running by default. + - On macOS, install and launch [XQuartz](https://www.xquartz.org/) (make sure to go to XQuartz > Preferences > Security and check "Allow client connections"). + - On Windows, install and launch [VcXsrv](https://sourceforge.net/projects/vcxsrv/) (make sure to configure it to disable access control). +- Install [VScode](https://code.visualstudio.com/download) and add [Ledger's extension](https://marketplace.visualstudio.com/items?itemName=LedgerHQ.ledger-dev-tools). +- Open a terminal and clone `app-boilerplate-rust` with `git clone git@github.com:LedgerHQ/app-boilerplate-rust.git`. +- Open the `app-boilerplate-rust` folder with VSCode. +- Use Ledger extension's sidebar menu or open the tasks menu with `ctrl + shift + b` (`command + shift + b` on a Mac) to conveniently execute actions : + - **Build** the app for the device model of your choice with `Build`. + - **Test** your binary on the [Speculos emulator](https://github.com/LedgerHQ/speculos) with `Run with emulator`. + - You can also **run functional tests**, load the app on a physical device, and more. + +ℹ️ The terminal tab of VSCode will show you what commands the extension runs behind the scene. + +## With a terminal + +### Prerequisites + +If you do not wish to use the [VS Code extension](#with-vs-code), you can follow the following steps to setup a development environment on Linux, Windows or MacOS. + +- The [ledger-app-dev-tools](https://github.com/LedgerHQ/ledger-app-builder/pkgs/container/ledger-app-builder%2Fledger-app-dev-tools) Docker image contains all the required tools and libraries to build, test and load an application on a device. You can download it from the ghcr.io docker repository: + +```shell +sudo docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest +``` + +- Make sure you have an X11 server running : + - On Ubuntu Linux, it should be running by default. + - On macOS, install and launch [XQuartz](https://www.xquartz.org/) (make sure to go to XQuartz > Preferences > Security and check "Allow client connections"). + - On Windows, install and launch [VcXsrv](https://sourceforge.net/projects/vcxsrv/) (make sure to configure it to disable access control). +- You can then enter into this development environment by executing the following command from the directory of the application (`git` repository): + - Linux (Ubuntu): + ```shell + sudo docker run --rm -ti --privileged -v "/dev/bus/usb:/dev/bus/usb" -v "$(realpath .):/app" --publish 5001:5001 --publish 9999:9999 -e DISPLAY=$DISPLAY -v '/tmp/.X11-unix:/tmp/.X11-unix' ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest + ``` + - macOS: + ```shell + sudo docker run --rm -ti --privileged -v "$(pwd -P):/app" --publish 5001:5001 --publish 9999:9999 -e DISPLAY='host.docker.internal:0' -v '/tmp/.X11-unix:/tmp/.X11-unix' ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest + ``` + - Windows (with PowerShell): + ```shell + docker run --rm -ti --privileged -v "$(Get-Location):/app" -e DISPLAY='host.docker.internal:0' --publish 5001:5001 --publish 9999:9999 ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest + ``` + +The application's code will be available from inside the docker container, you can proceed to the following compilation steps to build your app. + +### Building + +You can build the Mintlayer app with the following command executed in the root directory of the app. + +```bash +cargo ledger build nanox +``` + +This command will build the app for the Nano X, but you can use any supported device (`nanox`, `nanosplus`, `stax`, `flex`) + +### Testing + +#### Ragger functional tests + +This Mintlayer app comes with functional tests implemented with Ledger's [Ragger](https://github.com/LedgerHQ/ragger) test framework. + +- Install the tests requirements + +```bash +pip install -r tests/requirements.txt +``` + +- Run the functional tests : + +```shell +pytest tests/ --tb=short -v --device {nanosp | nanox | stax | flex} +``` + +#### Emulator + +You can also run the app directly on the [Speculos emulator](https://github.com/LedgerHQ/speculos) from the Docker container + +#### Nano S+ or X + +```bash +speculos --apdu-port 9999 --api-port 5000 --display headless --model nanosp target/nanosplus/release/mintlayer-app +``` + +:warning: UI is displayed on `localhost:5000` + +#### Stax or Flex + +```bash +speculos --apdu-port 9999 --api-port 5000 --model stax target/stax/release/mintlayer-app +``` + +You can also specify the seed phrase with -s "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" + +:warning: UI is displayed by your X server + +You can then send APDU using `ledgercomm` (`pip install ledgercomm`): + +``` +ledgercomm-send file test.apdu +``` + +### Loading on device + +:warning: Loading the built application on a device shall be performed out of the Docker container, by using [ledgerctl](https://github.com/LedgerHQ/ledgerctl): + +```shell +pip3 install ledgerwallet +``` + +ℹ️ Your device must be connected, unlocked and the screen showing the dashboard (not inside an application). + +For instance, for Flex: + +```bash +ledgerctl install -f target/flex/release/app_flex.json +``` + +## Continuous Integration + +The following workflows are executed in [GitHub Actions](https://github.com/features/actions) : + +- Ledger guidelines enforcer which verifies that an app is compliant with Ledger guidelines. The successful completion of this reusable workflow is a mandatory step for an app to be available on the Ledger application store. More information on the guidelines can be found in the repository [ledger-app-workflow](https://github.com/LedgerHQ/ledger-app-workflows) +- Compilation of the application for all supported devices in the [ledger-app-builder](https://github.com/LedgerHQ/ledger-app-builder) docker image +- End-to-end tests with the [Speculos](https://github.com/LedgerHQ/speculos) emulator and [ragger](https://github.com/LedgerHQ/ragger) (see [tests/](tests/)) +- Various lint checks : + - Source code lint checks with `cargo fmt` + - Python functional test code lint checks with `pylint` and `mypy` + +## Additional documentation + +For development guidelines related to the app's memory usage see [docs/memory_usage.md](docs/memory_usage.md). diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..25e883c --- /dev/null +++ b/build.rs @@ -0,0 +1,49 @@ +use std::process::Command; + +use image::{ImageFormat, ImageReader, Pixel}; + +fn main() { + println!("cargo:rerun-if-changed=script.ld"); + println!("cargo:rerun-if-changed=icons/mintlayer_14x14.gif"); + println!("cargo:rerun-if-changed=icons/mask_14x14.gif"); + + let path = std::path::PathBuf::from("icons"); + let reader = ImageReader::open(path.join("mintlayer_14x14.gif")).unwrap(); + let img = reader.decode().unwrap(); + let mut gray = img.into_luma8(); + + // Apply mask + let mask = ImageReader::open(path.join("mask_14x14.gif")) + .unwrap() + .decode() + .unwrap() + .into_luma8(); + + for (x, y, mask_pixel) in mask.enumerate_pixels() { + let mask_value = mask_pixel[0]; + let mut gray_pixel = *gray.get_pixel(x, y); + if mask_value == 0 { + gray_pixel = image::Luma([0]); + } else { + gray_pixel.invert(); + } + gray.put_pixel(x, y, gray_pixel); + } + + let glyph_path = std::path::PathBuf::from("glyphs"); + gray.save_with_format(glyph_path.join("home_nano_nbgl.png"), ImageFormat::Png) + .unwrap(); + + let output = Command::new("git") + .args(["rev-parse", "HEAD"]) + .output() + .expect("Failed to execute git command"); + + let git_hash = String::from_utf8(output.stdout).expect("Failed to convert git output to UTF-8"); + + // Expose the Git hash as an environment variable + println!("cargo:rustc-env=GIT_HASH={}", git_hash.trim()); + + // Rerun the build script if .git/HEAD changes + println!("cargo:rerun-if-changed=.git/HEAD"); +} diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000..8feef8a --- /dev/null +++ b/clippy.toml @@ -0,0 +1,3 @@ +# Clippy will complain if objects smaller that this are boxed. +# The default is 200 and we sometimes box slightly smaller objects. +too-large-for-stack = 150 diff --git a/crates/app-core/Cargo.toml b/crates/app-core/Cargo.toml new file mode 100644 index 0000000..024e4ca --- /dev/null +++ b/crates/app-core/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "mintlayer-app-core" +version.workspace = true +edition = "2021" + +[dependencies] +bech32 = { workspace = true, default-features = false, features = ["alloc"] } +chrono = { workspace = true, default-features = false, features = ["alloc"] } +hex = { workspace = true, default-features = false, features = ["alloc"] } +ledger_device_sdk.workspace = true +ledger_secure_sdk_sys.workspace = true + +mintlayer-core-primitives.workspace = true +mintlayer-messages.workspace = true + +[dev-dependencies] +ledger_device_sdk = { workspace = true, features = ["unit_test"] } +testmacro.workspace = true + +[features] +default = ["ledger_device_sdk/nano_nbgl"] +debug = ["ledger_device_sdk/debug"] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = [ + 'cfg(target_os, values("apex_p", "stax", "flex", "nanos", "nanox", "nanosplus"))', +] } diff --git a/crates/app-core/src/app_ui/address.rs b/crates/app-core/src/app_ui/address.rs new file mode 100644 index 0000000..daaa282 --- /dev/null +++ b/crates/app-core/src/app_ui/address.rs @@ -0,0 +1,46 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2023 Ledger SAS. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use crate::{ + app_ui::utils::{compress_public_key, load_glyph, to_address}, + StatusWord, +}; +use mintlayer_messages::mlcp::{CoinType, Destination, PublicKey}; + +use ledger_device_sdk::{ + ecc::ECPublicKey, + nbgl::{NbglAddressReview, NbglGlyph}, +}; + +pub fn ui_display_pk( + public_key: &ECPublicKey<65, T>, + coin_type: CoinType, +) -> Result { + let pk = compress_public_key(public_key)?; + + let dest = Destination::PublicKey(PublicKey::Secp256k1Schnorr(pk)); + let addr = to_address(&dest, coin_type)?; + + const MINTLAYER: NbglGlyph = load_glyph(); + + // Display the address confirmation screen. + Ok(NbglAddressReview::new() + .glyph(&MINTLAYER) + .review_title("Verify ML address") + .show(&addr)) +} diff --git a/crates/app-core/src/app_ui/menu.rs b/crates/app-core/src/app_ui/menu.rs new file mode 100644 index 0000000..b6dff58 --- /dev/null +++ b/crates/app-core/src/app_ui/menu.rs @@ -0,0 +1,32 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2023 Ledger SAS. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use ledger_device_sdk::nbgl::{NbglGlyph, NbglHomeAndSettings}; + +use crate::app_ui::utils::load_glyph; + +pub fn ui_menu_main() -> NbglHomeAndSettings { + const MINTLAYER: NbglGlyph = load_glyph(); + + // Display the home screen. + NbglHomeAndSettings::new().glyph(&MINTLAYER).infos( + "Mintlayer", + env!("CARGO_PKG_VERSION"), + env!("CARGO_PKG_AUTHORS"), + ) +} diff --git a/crates/app-core/src/app_ui/sign.rs b/crates/app-core/src/app_ui/sign.rs new file mode 100644 index 0000000..4222b50 --- /dev/null +++ b/crates/app-core/src/app_ui/sign.rs @@ -0,0 +1,594 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use alloc::string::String; +use alloc::{format, string::ToString}; +use core::fmt::Write; + +use crate::{ + app_ui::utils::{ + bech32m_encode, compress_public_key, load_glyph, to_address, to_public_key_hash, + }, + handlers::sign_tx::{CoinOrTokenId, InputCommand, TxParsingOutputsContext, TxType}, + StatusWord, +}; +use mintlayer_messages::{ + encode, + mlcp::{ + AccountCommand, AccountSpending, Amount, CoinType, Destination, IsTokenFreezable, + IsTokenUnfreezable, NftIssuance, OrderAccountCommand, OutputTimeLock, OutputValue, + PublicKey, TokenIssuance, TokenTotalSupply, TxOutput, VrfPublicKey, H256, + }, + AddrType, +}; + +use chrono::{TimeZone, Utc}; +use ledger_device_sdk::{ + ecc::ECPublicKey, + nbgl::{ + Field, NbglGlyph, NbglReview, NbglStreamingReview, NbglStreamingReviewStatus, + TransactionType, + }, +}; + +struct FormatedOutput { + name: &'static str, + value: String, +} + +pub fn ui_new_streaming_review() -> NbglStreamingReview { + const MINTLAYER: NbglGlyph = load_glyph(); + + NbglStreamingReview::new() + .glyph(&MINTLAYER) + .tx_type(TransactionType::Transaction) +} + +pub fn ui_start_streaming_review(review: &NbglStreamingReview) -> bool { + review.start("Review transaction", None) +} + +pub fn ui_streaming_review_show_input( + review: &NbglStreamingReview, + input: &InputCommand, + coin: CoinType, +) -> Result { + let input = format_input(input, coin)?; + + let fields = [Field { + name: input.name, + value: &input.value, + }]; + + let res = match review.next(&fields) { + NbglStreamingReviewStatus::Rejected => false, + NbglStreamingReviewStatus::Next | NbglStreamingReviewStatus::Skipped => true, + }; + + Ok(res) +} + +pub fn ui_streaming_review_show_output( + review: &NbglStreamingReview, + output: &TxOutput, + coin: CoinType, +) -> Result { + let output = format_output(output, coin)?; + + let fields = [Field { + name: output.name, + value: &output.value, + }]; + + let res = match review.next(&fields) { + NbglStreamingReviewStatus::Rejected => false, + NbglStreamingReviewStatus::Next | NbglStreamingReviewStatus::Skipped => true, + }; + + Ok(res) +} + +pub fn ui_approve_streaming_review( + review: &NbglStreamingReview, + ctx: &TxParsingOutputsContext, +) -> Result { + let coin = ctx.coin(); + let fees = ctx.summary().fees_iter().try_fold( + String::new(), + |mut acc, res| -> Result<_, StatusWord> { + let (coin_or_token, fee) = res?; + + match coin_or_token { + CoinOrTokenId::Coin => writeln!( + acc, + "{} {}", + format_amount(Amount::from_atoms(fee), coin), + coin.coin_ticker() + ) + .map_err(|_| StatusWord::TxDisplayFail)?, + + CoinOrTokenId::TokenId(token_id) => { + if fee != 0 { + writeln!( + acc, + "{fee} {}", + id_to_address(token_id, coin.token_id_address_prefix())? + ) + .map_err(|_| StatusWord::TxDisplayFail)? + } + } + }; + + Ok(acc) + }, + )?; + + let fields = [Field { + name: "Fees:", + value: &fees, + }]; + + match review.next(&fields) { + NbglStreamingReviewStatus::Rejected => return Ok(false), + NbglStreamingReviewStatus::Next | NbglStreamingReviewStatus::Skipped => {} + }; + + let title = transaction_title(&ctx.summary().tx_type()); + Ok(review.finish(title)) +} + +fn transaction_title(tx_type: &Option) -> &'static str { + match tx_type { + None | Some(TxType::ComplexTransaction) => "Sign transaction", + Some(TxType::Transfer) => "Sign transfer transaction", + Some(TxType::Burn) => "Sign burn transaction", + Some(TxType::Htlc) => "Sign create HTLC transaction", + Some(TxType::CreateDelegation) => "Sign create delegation transaction", + Some(TxType::DelegationStake) => "Sign stake delegation transaction", + Some(TxType::DelegationWithdrawal) => "Sign withdrawal delegation transaction", + Some(TxType::CreateStakePool) => "Sign create stake pool transaction", + Some(TxType::DecommissionStakePool) => "Sign decommission stake pool transaction", + Some(TxType::CreateNft) => "Sign create NFT transaction", + Some(TxType::CreateToken) => "Sign create token transaction", + Some(TxType::MintTokens) => "Sign mint tokens transaction", + Some(TxType::UnmintTokens) => "Sign unmint tokens transaction", + Some(TxType::FreezeToken) => "Sign freeze tokens transaction", + Some(TxType::UnfreezeToken) => "Sign unfreeze tokens transaction", + Some(TxType::LockTokenSupply) => "Sign lock token supply transaction", + Some(TxType::ChangeTokenAuthority) => "Sign change token authority transaction", + Some(TxType::ChangeTokenMetadataUri) => "Sign change token metadata URI transaction", + Some(TxType::CreateOrder) => "Sign create order transaction", + Some(TxType::FillOrder) => "Sign fill order transaction", + Some(TxType::FreezeOrder) => "Sign freeze order transaction", + Some(TxType::ConcludeOrder) => "Sign conclude order transaction", + Some(TxType::DataDeposit) => "Sign data deposit transaction", + } +} + +/// Displays a message for review and signing confirmation on the device. +/// +/// This function handles both printable text and raw binary data by +/// displaying UTF-8 content directly and falling back to hex encoding for other data. +/// +/// # Arguments +/// +/// * `message` - A byte slice (`&[u8]`) containing the message to be signed. +/// +/// # Returns +/// +/// * `Ok(true)` if the user approves the signing. +/// * `Ok(false)` if the user rejects. +/// * `Err(AppSW)` on error. +pub fn ui_display_message( + message: &[u8], + public_key: &ECPublicKey<65, T>, + coin_type: CoinType, + addr_type: AddrType, +) -> Result { + let pk = compress_public_key(public_key)?; + + let dest = match addr_type { + AddrType::PublicKey => Destination::PublicKey(PublicKey::Secp256k1Schnorr(pk)), + AddrType::PublicKeyHash => Destination::PublicKeyHash(to_public_key_hash(&pk)?), + }; + let addr = to_address(&dest, coin_type)?; + + let message_str = match core::str::from_utf8(message) { + Ok(s) if s.bytes().all(|b| (0x20..=0x7E).contains(&b)) => s.to_string(), + Ok(_) | Err(_) => format!("0x{}", hex::encode(message)), + }; + + let msg_fields = [ + Field { + name: "Address", + value: addr.as_str(), + }, + Field { + name: "Message", + value: message_str.as_str(), + }, + ]; + + const MINTLAYER: NbglGlyph = load_glyph(); + + // Create the NBGL review flow with titles appropriate for message signing. + let review: NbglReview = NbglReview::new() + .titles( + "Review message", // Initial title + "Cannot be undone", // Warning on the second screen + "Sign message", // Final confirmation prompt + ) + .tx_type(TransactionType::Message) + .glyph(&MINTLAYER); + + // Show the review screen with the defined fields and return the user's choice. + Ok(review.show(&msg_fields)) +} + +fn vrf_to_address(key: &VrfPublicKey, coin: CoinType) -> Result { + bech32m_encode(coin.vrf_public_key_address_prefix(), &encode(key)) +} + +fn id_to_address(id: &H256, hrp: &str) -> Result { + bech32m_encode(hrp, &id.0) +} + +fn format_amount(amount: Amount, coin: CoinType) -> String { + let decimals = coin.coin_decimals() as usize; + let mantissa = amount.into_atoms(); + + // ceil(log10(u128::MAX)) + 1 for decimal point = 40 + // This is not the maximum possible length, but a reasonable expectation of it. + let mut buffer = String::with_capacity(40); + write!(&mut buffer, "{mantissa:0>width$}", width = decimals + 1).unwrap(); + buffer.insert(buffer.len() - decimals, '.'); + buffer +} + +fn format_atoms(amount: Amount) -> String { + amount.into_atoms().to_string() +} + +fn format_value(value: &OutputValue, coin: CoinType) -> Result { + match value { + OutputValue::Coin(amount) => Ok(format!("Coins: {}", format_amount(*amount, coin))), + OutputValue::TokenV1(token_id, amount) => Ok(format!( + "Token: {} {}", + id_to_address(token_id.hash(), coin.token_id_address_prefix())?, + format_atoms(*amount) + )), + } +} + +fn format_timestamp(seconds_u64: u64) -> Result { + let seconds_i64: i64 = seconds_u64 + .try_into() + .map_err(|_| StatusWord::TxLockTimeInvalid)?; + let datetime = Utc + .timestamp_opt(seconds_i64, 0) + .earliest() + .ok_or(StatusWord::TxLockTimeInvalid)?; + + Ok(datetime.format("%Y-%m-%d %H:%M:%S").to_string()) +} + +fn format_lock(lock: &OutputTimeLock) -> Result { + let s = match lock { + OutputTimeLock::UntilHeight(h) => format!("Lock until block height {}", h.0), + OutputTimeLock::UntilTime(t) => format!("Lock until {}", format_timestamp(t.0 .0)?), + OutputTimeLock::ForBlockCount(b) => format!("Lock for {} blocks", b.0), + OutputTimeLock::ForSeconds(s) => format!("Lock for {} seconds", s.0), + }; + Ok(s) +} + +/// Formats a transaction output into a FormatedOutput. +/// +/// # Arguments +/// * `output` - A reference to the `TxOutput` enum variant to format. +/// * `coin` - The coin information, used for formatting amounts. +/// +/// # Returns +/// A FormatedOutput containing the title and value of the output. +fn format_output(output: &TxOutput, coin: CoinType) -> Result { + let (name, value) = match output { + TxOutput::Transfer(value, destination) => ( + "Transfer", + format!( + "Destination: {}\n{}\n", + to_address(destination, coin)?, + format_value(value, coin)? + ), + ), + + TxOutput::LockThenTransfer(value, destination, lock) => { + let address_short = format!( + "Destination: {}\n{}\n{}\n", + to_address(destination, coin)?, + format_lock(lock)?, + format_value(value, coin)? + ); + if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + ("LockThenXfer", address_short) + } else { + ("Lock then Transfer", address_short) + } + } + + TxOutput::Burn(value) => ("Burn", format_value(value, coin)?), + + TxOutput::CreateStakePool(pool_id, data) => { + let address_short = format!( + "Pool ID: {}\nStaker key: {}\nDecommission key: {}\nVRF public key: {}\nMargin ratio per thousand: {}\nCost per block: {}\nPledge{}\n", + id_to_address(pool_id.hash(), coin.pool_id_address_prefix())?, to_address(&data.staker, coin)?, to_address(&data.decommission_key, coin)?, vrf_to_address(&data.vrf_public_key, coin)?, data.margin_ratio_per_thousand.0, format_amount(data.cost_per_block, coin), + format_amount(data.pledge, coin)); + ("Create staking pool", address_short) + } + + TxOutput::ProduceBlockFromStake(destination, _pool_id) => { + let name = if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + "Prod block" + } else { + "Produce block from stake" + }; + + ( + name, + format!("New staker key: {}", to_address(destination, coin)?), + ) + } + TxOutput::CreateDelegationId(destination, pool_id) => { + let address_short = format!( + "Address: {}\nPoolId: {}", + to_address(destination, coin)?, + id_to_address(pool_id.hash(), coin.pool_id_address_prefix())? + ); + + let name = if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + "Create deleg" + } else { + "Create delegation" + }; + + (name, address_short) + } + + TxOutput::DelegateStaking(amount, delegation_id) => { + let name = if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + "Deleg stake" + } else { + "Delegate staking" + }; + + ( + name, + format!( + "\n{}\n{}", + id_to_address(delegation_id.hash(), coin.delegation_id_address_prefix())?, + format_value(&OutputValue::Coin(*amount), coin)?, + ), + ) + } + TxOutput::IssueFungibleToken(x) => { + let TokenIssuance::V1(data) = x; + + let ticker = String::from_utf8_lossy(data.token_ticker.as_ref()); + let metadata_uri = String::from_utf8_lossy(data.metadata_uri.as_ref()); + + let total_supply_str = match data.total_supply { + TokenTotalSupply::Unlimited => "UNLIMITED".to_string(), + TokenTotalSupply::Lockable => "LOCKABLE".to_string(), + TokenTotalSupply::Fixed(amount) => { + let formatted_amount = format_amount(amount, coin); + format!("FIXED {}", formatted_amount) + } + }; + let is_freezable = match data.is_freezable { + IsTokenFreezable::Yes => "Yes", + IsTokenFreezable::No => "No", + }; + + let address_short = format!( + "Ticker: {}\nAuthority: {}\nMetadata URI: {}\nTotal token supply: {}\nNumber of decimals: {}\nIs freezable: {}", + ticker, to_address(&data.authority, coin)?, metadata_uri, total_supply_str, data.number_of_decimals, is_freezable + ); + let name = if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + "Issue token" + } else { + "Issue fungible token" + }; + + (name, address_short) + } + + TxOutput::IssueNft(_nft_id, data, destination) => { + let NftIssuance::V0(data) = data; + let address_short = format!( + "Name: {}\nCreator: {}\nTicker: {}\nAddress: {}\nIcon URI: {}\nAdditional metadata URI: {}\nMedia URI: {}", + String::from_utf8_lossy(data.name.as_ref()), + data.creator.clone().map(|creator| to_address(&Destination::PublicKey(creator), coin)).transpose()?.unwrap_or_default(), + String::from_utf8_lossy(data.ticker.as_ref()), + to_address(destination, coin)?, + String::from_utf8_lossy(data.icon_uri.as_ref()), + String::from_utf8_lossy(data.additional_metadata_uri.as_ref()), + String::from_utf8_lossy(data.media_uri.as_ref()) + ); + let name = if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + "Issue NFT" + } else { + "Issue NFT token" + }; + + (name, address_short) + } + + TxOutput::DataDeposit(data) => ("Data deposit", hex::encode(data)), + + TxOutput::Htlc(value, data) => { + let address_short = format!( + "Secret hash: {}\nSpend key: {}\nRefund key: {}\nRefund time lock: {}\n{}", + hex::encode(data.secret_hash.0), + to_address(&data.spend_key, coin)?, + to_address(&data.refund_key, coin)?, + format_lock(&data.refund_timelock)?, + format_value(value, coin)? + ); + ("HTLC", address_short) + } + + TxOutput::CreateOrder(data) => { + let ask_amount = format_value(&data.ask, coin)?; + let give_amount = format_value(&data.give, coin)?; + let address_short = format!( + "Conclude key: {}\nAsk: {}\nGive: {}", + to_address(&data.conclude_key, coin)?, + ask_amount, + give_amount + ); + ("Create order", address_short) + } + }; + + Ok(FormatedOutput { name, value }) +} + +fn format_input(input: &InputCommand, coin: CoinType) -> Result { + let (name, value) = match input { + InputCommand::AccountSpending(cmd) => match cmd { + AccountSpending::DelegationBalance(delegation_id, amount) => { + let address_short = format!( + "Delegation ID: {}\nAmount: {}", + id_to_address(delegation_id.hash(), coin.delegation_id_address_prefix())?, + format_amount(*amount, coin) + ); + if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + ("Del Wdrwl", address_short) + } else { + ("Delegation withdrawal", address_short) + } + } + }, + InputCommand::AccountCommand(cmd) => match cmd { + AccountCommand::MintTokens(token_id, amount) => { + let address_short = format!( + "Token ID: {}\nAmount: {}", + id_to_address(token_id.hash(), coin.token_id_address_prefix())?, + format_amount(*amount, coin) + ); + ("Mint tokens", address_short) + } + AccountCommand::UnmintTokens(token_id) => { + let address_short = format!( + "Token ID: {}", + id_to_address(token_id.hash(), coin.token_id_address_prefix())?, + ); + ("Unmint tokens", address_short) + } + AccountCommand::LockTokenSupply(token_id) => { + let address_short = format!( + "Token ID: {}", + id_to_address(token_id.hash(), coin.token_id_address_prefix())? + ); + if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + ("Lock token", address_short) + } else { + ("Lock token supply", address_short) + } + } + AccountCommand::FreezeToken(token_id, is_unfreezable) => { + let address_short = format!( + "Token ID: {}\nIs unfreezable: {}", + id_to_address(token_id.hash(), coin.token_id_address_prefix())?, + if *is_unfreezable == IsTokenUnfreezable::Yes { + "Yes" + } else { + "No" + } + ); + ("Freeze token", address_short) + } + AccountCommand::UnfreezeToken(token_id) => { + let address_short = format!( + "Token ID: {}", + id_to_address(token_id.hash(), coin.token_id_address_prefix())?, + ); + if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + ("Unfrz token", address_short) + } else { + ("Unfreeze token", address_short) + } + } + AccountCommand::ChangeTokenAuthority(token_id, new_authority) => { + let address_short = format!( + "Token ID: {}\nNew authority: {}", + id_to_address(token_id.hash(), coin.token_id_address_prefix())?, + to_address(new_authority, coin)? + ); + if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + ("Chg token auth", address_short) + } else { + ("Change token authority", address_short) + } + } + AccountCommand::ChangeTokenMetadataUri(token_id, new_metadata_uri) => { + let address_short = format!( + "Token ID: {}\nNew metadata URI: {}", + id_to_address(token_id.hash(), coin.token_id_address_prefix())?, + String::from_utf8_lossy(new_metadata_uri) + ); + if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + ("Chg token meta", address_short) + } else { + ("Change token metadata URI", address_short) + } + } + AccountCommand::ConcludeOrder(_) | AccountCommand::FillOrder(_, _, _) => { + return Err(StatusWord::OrdersV0NotSupported) + } + }, + InputCommand::OrderCommand(cmd) => match cmd { + OrderAccountCommand::FillOrder(order_id, fill_amount) => { + let address_short = format!( + "Order ID: {}\nFill amount: {}", + id_to_address(order_id.hash(), coin.order_id_address_prefix())?, + format_amount(*fill_amount, coin), + ); + ("Fill order", address_short) + } + OrderAccountCommand::FreezeOrder(order_id) => { + let address_short = format!( + "Order ID: {}", + id_to_address(order_id.hash(), coin.order_id_address_prefix())? + ); + ("Freeze order", address_short) + } + OrderAccountCommand::ConcludeOrder(order_id) => { + let address_short = format!( + "Order ID: {}", + id_to_address(order_id.hash(), coin.order_id_address_prefix())? + ); + if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + ("Conclude ord", address_short) + } else { + ("Conclude order", address_short) + } + } + }, + }; + + Ok(FormatedOutput { name, value }) +} diff --git a/crates/app-core/src/app_ui/utils.rs b/crates/app-core/src/app_ui/utils.rs new file mode 100644 index 0000000..92a5200 --- /dev/null +++ b/crates/app-core/src/app_ui/utils.rs @@ -0,0 +1,106 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use alloc::string::String; + +use ledger_device_sdk::{ + ecc::ECPublicKey, + hash::{blake2::Blake2b_512, HashInit}, + include_gif, + nbgl::NbglGlyph, +}; + +use crate::StatusWord; +use mintlayer_messages::{ + encode, + mlcp::{CoinType, Destination, PublicKeyHash, Secp256k1PublicKey}, +}; + +pub fn bech32m_encode(hrp: &str, data: &[u8]) -> Result { + let parsed_hrp = bech32::Hrp::parse(hrp).map_err(|_| StatusWord::TxAddressFail)?; + + let encoded = bech32::encode::(parsed_hrp, data) + .map_err(|_| StatusWord::TxAddressFail)?; + + Ok(encoded) +} + +pub fn to_address(destination: &Destination, coin: CoinType) -> Result { + let hrp = coin.address_prefix(destination.into()); + bech32m_encode(hrp, &encode(destination)) +} + +/// Load glyph from file with include_gif macro. Creates an NBGL compatible glyph. +pub const fn load_glyph() -> NbglGlyph<'static> { + #[cfg(target_os = "apex_p")] + const MINTLAYER: NbglGlyph = + NbglGlyph::from_include(include_gif!("../../glyphs/mintlayer_48x48.png", NBGL)); + #[cfg(any(target_os = "stax", target_os = "flex"))] + const MINTLAYER: NbglGlyph = + NbglGlyph::from_include(include_gif!("../../glyphs/mintlayer_64x64.gif", NBGL)); + #[cfg(any(target_os = "nanosplus", target_os = "nanox"))] + const MINTLAYER: NbglGlyph = + NbglGlyph::from_include(include_gif!("../../icons/mintlayer_14x14.gif", NBGL)); + + MINTLAYER +} + +pub fn compress_public_key( + public_key: &ECPublicKey<65, T>, +) -> Result { + let uncompressed_key = &public_key.pubkey; + if uncompressed_key[0] != 0x04 { + return Err(StatusWord::InvalidUncompressedPublicKey); + } + + let mut compressed_key = [0u8; 33]; + + let y_coordinate = &uncompressed_key[33..65]; + let prefix = if y_coordinate[31].is_multiple_of(2) { + 0x02 + } else { + 0x03 + }; + + compressed_key[0] = prefix; + + let x_coordinate = &uncompressed_key[1..33]; + compressed_key[1..].copy_from_slice(x_coordinate); + + Ok(Secp256k1PublicKey(compressed_key)) +} + +pub fn to_public_key_hash(pk: &Secp256k1PublicKey) -> Result { + let mut blake2b256 = Blake2b_512::new(); + let mut public_key_hash: [u8; 64] = [0u8; 64]; + + blake2b256 + .update(&[0]) + .map_err(|_| StatusWord::TxHashFail)?; + blake2b256 + .update(&pk.0) + .map_err(|_| StatusWord::TxHashFail)?; + + blake2b256 + .finalize(&mut public_key_hash) + .map_err(|_| StatusWord::TxHashFail)?; + + let mut pkh = [0u8; 20]; + pkh.copy_from_slice(&public_key_hash[0..20]); + + Ok(PublicKeyHash(pkh)) +} diff --git a/crates/app-core/src/errors.rs b/crates/app-core/src/errors.rs new file mode 100644 index 0000000..364bb55 --- /dev/null +++ b/crates/app-core/src/errors.rs @@ -0,0 +1,56 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use ledger_device_sdk::ecc::CxError; +use mintlayer_messages::StatusWord; + +pub fn cx_err_to_status(e: CxError) -> StatusWord { + match e { + CxError::Carry => StatusWord::EccCarry, + CxError::Locked => StatusWord::EccLocked, + CxError::Unlocked => StatusWord::EccUnlocked, + CxError::NotLocked => StatusWord::EccNotLocked, + CxError::NotUnlocked => StatusWord::EccNotUnlocked, + CxError::InternalError => StatusWord::EccInternalError, + CxError::InvalidParameterSize => StatusWord::EccInvalidParameterSize, + CxError::InvalidParameterValue => StatusWord::EccInvalidParameterValue, + CxError::InvalidParameter => StatusWord::EccInvalidParameter, + CxError::NotInvertible => StatusWord::EccNotInvertible, + CxError::Overflow => StatusWord::EccOverflow, + CxError::MemoryFull => StatusWord::EccMemoryFull, + CxError::NoResidue => StatusWord::EccNoResidue, + CxError::PointAtInfinity => StatusWord::EccPointAtInfinity, + CxError::InvalidPoint => StatusWord::EccInvalidPoint, + CxError::InvalidCurve => StatusWord::EccInvalidCurve, + CxError::GenericError => StatusWord::EccGenericError, + } +} + +pub fn sdk_err_to_status(e: ledger_device_sdk::io::StatusWords) -> StatusWord { + match e { + ledger_device_sdk::io::StatusWords::Ok => StatusWord::Ok, + ledger_device_sdk::io::StatusWords::BadCla => StatusWord::ClaNotSupported, + ledger_device_sdk::io::StatusWords::NothingReceived => StatusWord::NothingReceived, + ledger_device_sdk::io::StatusWords::BadIns => StatusWord::InsNotSupported, + ledger_device_sdk::io::StatusWords::BadP1P2 => StatusWord::WrongP1P2, + ledger_device_sdk::io::StatusWords::BadLen => StatusWord::WrongApduLength, + ledger_device_sdk::io::StatusWords::UserCancelled => StatusWord::Deny, + ledger_device_sdk::io::StatusWords::Unknown => StatusWord::Unknown, + ledger_device_sdk::io::StatusWords::Panic => StatusWord::Panic, + ledger_device_sdk::io::StatusWords::DeviceLocked => StatusWord::DeviceLocked, + } +} diff --git a/crates/app-core/src/handlers/get_public_key.rs b/crates/app-core/src/handlers/get_public_key.rs new file mode 100644 index 0000000..86b7c44 --- /dev/null +++ b/crates/app-core/src/handlers/get_public_key.rs @@ -0,0 +1,55 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use crate::app_ui::address::ui_display_pk; +use crate::StatusWord; +use mintlayer_messages::{ + mlcp::CoinType, ChainCode, GetPublicKeyResponse, PublicKey, PublicKeyReq, +}; + +use ledger_device_sdk::ecc::{Secp256k1, SeedDerive}; + +// Path should be at least [bip44, coin_type, account_index] +const MIN_PATH_LEN: usize = 3; + +pub fn handle_get_public_key( + req: PublicKeyReq, + display: bool, +) -> Result { + if req.path.as_ref().len() < MIN_PATH_LEN { + return Err(StatusWord::InvalidPath); + } + let coin_type: CoinType = req.coin_type.into(); + if req.path.as_ref()[1] != coin_type.bip44_coin_type() { + return Err(StatusWord::InvalidPath); + } + + let (k, cc) = Secp256k1::derive_from(req.path.as_ref()); + let pk = k.public_key().map_err(|_| StatusWord::KeyDeriveFail)?; + let code = cc.ok_or(StatusWord::KeyDeriveFail)?; + + // Display address on device if requested + if display && !ui_display_pk(&pk, req.coin_type.into())? { + return Err(StatusWord::Deny); + } + let response = GetPublicKeyResponse { + public_key: PublicKey(pk.pubkey), + chain_code: ChainCode(code.value), + }; + + Ok(response) +} diff --git a/crates/app-core/src/handlers/sign_message.rs b/crates/app-core/src/handlers/sign_message.rs new file mode 100644 index 0000000..5a60d55 --- /dev/null +++ b/crates/app-core/src/handlers/sign_message.rs @@ -0,0 +1,131 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use crate::{ + app_ui::sign::ui_display_message, errors::cx_err_to_status, handlers::utils::mintlayer_hash, + DataContext, StatusWord, +}; +use mintlayer_messages::{ + mlcp::CoinType, AddrType, Bip32Path, MsgSignatureResponse, SignMessageReq, SignatureResponse, +}; + +use alloc::vec::Vec; +use ledger_device_sdk::ecc::{ECPrivateKey, Secp256k1, SeedDerive}; +use ledger_secure_sdk_sys::*; + +pub struct SignMessageContext { + path: Bip32Path, + coin: CoinType, + addr_type: AddrType, + review_finished: bool, +} + +impl SignMessageContext { + pub fn new(req: SignMessageReq) -> Self { + Self { + path: req.path, + coin: req.coin.into(), + addr_type: req.addr_type, + review_finished: false, + } + } + + pub fn finished(&self) -> bool { + self.review_finished + } +} + +pub fn setup_sign_message(req: SignMessageReq) -> DataContext { + DataContext::SignMessageContext(SignMessageContext::new(req)) +} + +pub fn handle_sign_message( + message: &[u8], + ctx: &mut SignMessageContext, +) -> Result { + let private_key = Secp256k1::derive_from_path(ctx.path.as_ref()); + let public_key = private_key + .public_key() + .map_err(|_| StatusWord::KeyDeriveFail)?; + + // Display review. If user approves sign it. + // Otherwise, return a "deny" status word. + if ui_display_message(message, &public_key, ctx.coin, ctx.addr_type)? { + ctx.review_finished = true; + Ok(compute_signature(&private_key, message)?) + } else { + ctx.review_finished = true; + Err(StatusWord::Deny) + } +} + +fn compute_signature( + private_key: &ECPrivateKey, + message: &[u8], +) -> Result { + const MESSAGE_MAGIC_PREFIX: &str = "===MINTLAYER MESSAGE BEGIN===\n"; + const MESSAGE_MAGIC_SUFFIX: &str = "\n===MINTLAYER MESSAGE END==="; + + let message = MESSAGE_MAGIC_PREFIX + .as_bytes() + .iter() + .chain(message.iter()) + .chain(MESSAGE_MAGIC_SUFFIX.as_bytes().iter()) + .copied() + .collect::>(); + + let message_hash = mintlayer_hash(&message)?; + let message_hash2 = mintlayer_hash(message_hash.as_bytes())?; + + let sig = schnorr_sign(private_key, message_hash2.as_bytes())?; + + let response = MsgSignatureResponse { + signature: SignatureResponse(sig), + }; + + Ok(response) +} + +pub fn schnorr_sign( + private_key: &ECPrivateKey, + msg: &[u8], +) -> Result<[u8; 64], StatusWord> { + const HASH_ALGORITHM_ID: u8 = CX_SHA256; + const SIGNING_MODE: u32 = CX_ECSCHNORR_BIP0340 | CX_RND_PROVIDED | CX_LAST; + + let mut sig = [0u8; 64]; + let mut sig_len = 64; + + // The `unsafe` block is required for FFI. + let err_code = unsafe { + cx_ecschnorr_sign_no_throw( + private_key as *const ECPrivateKey as *const cx_ecfp_256_private_key_s, + SIGNING_MODE, + HASH_ALGORITHM_ID, + msg.as_ptr(), + msg.len(), + sig.as_mut_ptr(), + &mut sig_len, + ) + }; + + if err_code != CX_OK { + Err(cx_err_to_status(err_code.into())) + } else { + Ok(sig) + } +} diff --git a/crates/app-core/src/handlers/sign_tx/mod.rs b/crates/app-core/src/handlers/sign_tx/mod.rs new file mode 100644 index 0000000..cbde975 --- /dev/null +++ b/crates/app-core/src/handlers/sign_tx/mod.rs @@ -0,0 +1,493 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use alloc::{boxed::Box, vec::Vec}; + +use crate::{ + app_ui::sign::{ + ui_approve_streaming_review, ui_new_streaming_review, ui_start_streaming_review, + ui_streaming_review_show_input, ui_streaming_review_show_output, + }, + handlers::{sign_message::schnorr_sign, utils::mintlayer_hash}, + DataContext, StatusWord, +}; +use mintlayer_messages::{ + encode_as_compact, encode_to, + mlcp::{CoinType as PCoinType, SighashInputCommitment, H256}, + CoinType, Encode, InputAddressPath, Response, SignTxReq, SignatureResponse, TxInputReq, + TxInputSignatureResponse, TxMetadataReq, TxMetadataV1Req, TxMetadataVersionReq, TxOutputReq, +}; + +use ledger_device_sdk::{ + ecc::{Secp256k1, SeedDerive}, + hash::{blake2::Blake2b_512, HashInit}, + nbgl::{NbglSpinner, NbglStreamingReview}, +}; + +mod summary_collector; +use summary_collector::TxSummaryCollector; +pub use summary_collector::{CoinOrTokenId, InputCommand, TxType}; + +const BIP44: u32 = 44 + (1 << 31); + +// BIP44/COIN/ACCOUNT/PURPOSE/INDEX +const DERIVATION_PATH_LEN: usize = 5; +// DERIVATION_PATH_LEN without the BIP44 and COIN as they are the same for all +const COMPRESSED_DERIVATION_PATH_LEN: usize = 3; + +// we try to save a few bytes instead of using usize for indexes, +// u32 is enough to cover max possible number of inputs and outputs +type Index = u32; + +pub struct InputCompressed { + pub path: [u32; COMPRESSED_DERIVATION_PATH_LEN], + pub input_idx: Index, + pub multisig_idx: Option, +} + +impl InputCompressed { + fn new(addr: InputAddressPath, input_idx: Index, coin: PCoinType) -> Result { + let path = addr.path.as_ref(); + if path.len() != DERIVATION_PATH_LEN { + return Err(StatusWord::TxInvalidInputPath); + } + + if path[0] != BIP44 { + return Err(StatusWord::TxInvalidInputPath); + } + + if path[1] != coin.bip44_coin_type() { + return Err(StatusWord::TxInvalidInputPath); + } + + Ok(Self { + path: path[2..] + .try_into() + .map_err(|_| StatusWord::TxInvalidInputPath)?, + input_idx, + multisig_idx: addr.multisig_idx, + }) + } +} + +pub struct TxMetadata { + coin: PCoinType, + num_inputs: Index, + num_outputs: Index, +} + +pub struct TxParsingInputsContext { + metadata: TxMetadata, + + tx_hasher: Blake2b_512, + input_commitments_hasher: Blake2b_512, + + summary: TxSummaryCollector, + inputs: Vec, + + spinner: NbglSpinner, + + num_inputs_parsed: Index, +} + +pub struct TxParsingInputCommitmentsContext { + metadata: TxMetadata, + + tx_hasher: Blake2b_512, + input_commitments_hasher: Blake2b_512, + input_commitments_hash: [u8; 64], + + summary: TxSummaryCollector, + inputs: Vec, + + spinner: NbglSpinner, + + num_inputs_parsed: Index, +} + +impl TxParsingInputCommitmentsContext { + fn advance_next_input_additional_info_step( + mut self: Box, + review: &NbglStreamingReview, + ) -> Result { + let finished_with_inputs = self.num_inputs_parsed >= (self.metadata.num_inputs - 1); + + if finished_with_inputs { + // Make sure the hashes match before continuing with the outputs + let mut input_commitments_hash: [u8; 64] = [0u8; 64]; + self.input_commitments_hasher + .finalize(&mut input_commitments_hash) + .map_err(|_| StatusWord::TxHashFail)?; + + if input_commitments_hash != self.input_commitments_hash { + return Err(StatusWord::DifferentInputCommitmentHash); + } + + if !ui_start_streaming_review(review) { + return Err(StatusWord::Deny); + } + + if let Some(command) = self.summary.input_command() { + if !ui_streaming_review_show_input(review, command, self.metadata.coin)? { + return Err(StatusWord::Deny); + } + } + + self.tx_hasher + .update(&encode_as_compact(self.metadata.num_outputs)) + .map_err(|_| StatusWord::TxHashFail)?; + let new_context = TxParsingContext::ParsingOutputs(Box::new(TxParsingOutputsContext { + metadata: self.metadata, + + tx_hasher: self.tx_hasher, + + summary: self.summary, + inputs: self.inputs, + + spinner: self.spinner, + + num_outputs_parsed: 0, + })); + Ok(new_context) + } else { + self.num_inputs_parsed += 1; + Ok(TxParsingContext::ParsingInputCommitments(self)) + } + } +} + +impl TxParsingInputsContext { + fn advance_next_input_step(mut self: Box) -> Result { + self.num_inputs_parsed += 1; + let finished_with_inputs = self.num_inputs_parsed >= self.metadata.num_inputs; + + if finished_with_inputs { + if self.inputs.is_empty() { + return Err(StatusWord::NothingToSign); + } + + // Update hash for input commitments and proceed with outputs + self.tx_hasher + .update(&self.metadata.num_inputs.to_le_bytes()) + .map_err(|_| StatusWord::TxHashFail)?; + + let mut input_commitments_hash: [u8; 64] = [0u8; 64]; + self.input_commitments_hasher + .finalize(&mut input_commitments_hash) + .map_err(|_| StatusWord::TxHashFail)?; + + Ok(TxParsingContext::ParsingInputCommitments(Box::new( + TxParsingInputCommitmentsContext { + metadata: self.metadata, + tx_hasher: self.tx_hasher, + input_commitments_hasher: Blake2b_512::new(), + input_commitments_hash, + summary: self.summary, + inputs: self.inputs, + spinner: self.spinner, + num_inputs_parsed: 0, + }, + ))) + } else { + Ok(TxParsingContext::ParsingInputs(self)) + } + } +} + +pub struct TxParsingOutputsContext { + metadata: TxMetadata, + + tx_hasher: Blake2b_512, + + summary: TxSummaryCollector, + inputs: Vec, + + spinner: NbglSpinner, + + num_outputs_parsed: Index, +} + +impl TxParsingOutputsContext { + pub fn coin(&self) -> PCoinType { + self.metadata.coin + } + + pub fn summary(&self) -> &TxSummaryCollector { + &self.summary + } + + fn advance_next_output_state( + mut self: Box, + review: &NbglStreamingReview, + ) -> Result { + if self.num_outputs_parsed < (self.metadata.num_outputs - 1) { + self.num_outputs_parsed += 1; + Ok(TxParsingContext::ParsingOutputs(self)) + } else { + // Finalize the tx hash for signing + let mut message_hash: [u8; 64] = [0u8; 64]; + self.tx_hasher + .finalize(&mut message_hash) + .map_err(|_| StatusWord::TxHashFail)?; + + let tx_hash = mintlayer_hash(&message_hash[0..32])?; + + if ui_approve_streaming_review(review, &self)? { + Ok(TxParsingContext::Signing(Box::new(TxSigningContext { + metadata: self.metadata, + inputs: self.inputs, + spinner: self.spinner, + num_inputs_signed: 0, + tx_hash, + }))) + } else { + Err(StatusWord::Deny) + } + } + } +} + +pub struct TxSigningContext { + metadata: TxMetadata, + tx_hash: H256, + + inputs: Vec, + + spinner: NbglSpinner, + + num_inputs_signed: Index, +} + +impl TxSigningContext { + fn compute_signature_and_append( + mut self: Box, + ) -> Result<(TxInputSignatureResponse, TxParsingContext), StatusWord> { + let address = self + .inputs + .get(self.num_inputs_signed as usize) + .ok_or(StatusWord::WrongContext)?; + + let [p1, p2, p3] = address.path; + let addr = [BIP44, self.metadata.coin.bip44_coin_type(), p1, p2, p3]; + + let private_key = Secp256k1::derive_from_path(&addr); + let sig = schnorr_sign(&private_key, self.tx_hash.as_bytes())?; + + let signature = SignatureResponse(sig); + let input_idx = address.input_idx; + let multisig_idx = address.multisig_idx; + + let has_next = ((self.num_inputs_signed + 1) as usize) < self.inputs.len(); + + let response = TxInputSignatureResponse { + signature, + multisig_idx, + input_idx, + has_next, + }; + + let new_ctx = if has_next { + self.num_inputs_signed += 1; + TxParsingContext::Signing(self) + } else { + TxParsingContext::Finished + }; + + Ok((response, new_ctx)) + } +} + +pub enum TxParsingContext { + ParsingInputs(Box), + ParsingInputCommitments(Box), + ParsingOutputs(Box), + Signing(Box), + Finished, +} + +impl TxParsingContext { + pub fn from_v1( + coin: CoinType, + TxMetadataV1Req { + num_inputs, + num_outputs, + }: TxMetadataV1Req, + ) -> Result { + const VERSION_1: u8 = 1; + let mut tx_hasher = Blake2b_512::new(); + // mode + tx_hasher + .update(b"\x01") + .map_err(|_| StatusWord::TxHashFail)?; + // version + tx_hasher + .update(&[VERSION_1]) + .map_err(|_| StatusWord::TxHashFail)?; + // flags + tx_hasher + .update(&[0; 16]) + .map_err(|_| StatusWord::TxHashFail)?; + + tx_hasher + .update(&num_inputs.to_le_bytes()) + .map_err(|_| StatusWord::TxHashFail)?; + + Ok(Self::ParsingInputs(Box::new(TxParsingInputsContext { + metadata: TxMetadata { + coin: coin.into(), + num_inputs, + num_outputs, + }, + tx_hasher, + spinner: NbglSpinner::new(), + summary: TxSummaryCollector::new(), + num_inputs_parsed: 0, + input_commitments_hasher: Blake2b_512::new(), + inputs: Vec::new(), + }))) + } + + /// Shows a spinner while processing the inputs and input commitments if there are more than a few + /// as well as while signing and returning the signatures. + pub fn show_spinner(&mut self) { + let (metadata, spinner) = match self { + Self::ParsingInputs(ctx) => (&ctx.metadata, &mut ctx.spinner), + Self::ParsingInputCommitments(ctx) => (&ctx.metadata, &mut ctx.spinner), + Self::Signing(ctx) => { + ctx.spinner.show("Signing..."); + return; + } + // While parsing outputs we are showing the review and not the spinner + Self::ParsingOutputs(_) | Self::Finished => return, + }; + + // We show a spinner while processing the inputs and input commitments if there are more than 5 + // 5 was chosen somewhat arbitrarily + let transaction_has_many_inputs = metadata.num_inputs > 5; + + if transaction_has_many_inputs { + spinner.show("Parsing transaction..."); + } + } + + pub fn finished(&self) -> bool { + matches!(self, Self::Finished) + } +} + +pub fn setup_sign_tx(req: TxMetadataReq) -> Result { + let mut tx_ctx = match req.version { + TxMetadataVersionReq::V1(v1_req) => TxParsingContext::from_v1(req.coin, v1_req)?, + }; + + tx_ctx.show_spinner(); + + Ok(DataContext::TxContext(tx_ctx, ui_new_streaming_review())) +} + +fn handle_input_req( + req: Box, + mut ctx: Box, +) -> Result { + let num_inputs_parsed = ctx.num_inputs_parsed; + let compressed_inputs = req + .addresses + .into_iter() + .map(|a| InputCompressed::new(a, num_inputs_parsed, ctx.metadata.coin)) + .collect::, StatusWord>>()?; + ctx.inputs.extend(compressed_inputs); + + ctx.summary.process_input(&req.inp)?; + + let (input, commitment) = req.inp.into_input_and_commitment(); + update_hash(&commitment, &mut ctx.input_commitments_hasher)?; + update_hash(&input, &mut ctx.tx_hasher)?; + ctx.advance_next_input_step() +} + +fn handle_input_commitment_req( + req: &SighashInputCommitment, + mut ctx: Box, + review: &NbglStreamingReview, +) -> Result { + update_hash(req, &mut ctx.input_commitments_hasher)?; + update_hash(req, &mut ctx.tx_hasher)?; + ctx.advance_next_input_additional_info_step(review) +} + +fn handle_output_req( + req: &TxOutputReq, + mut ctx: Box, + review: &NbglStreamingReview, +) -> Result { + if ui_streaming_review_show_output(review, &req.out, ctx.metadata.coin)? { + ctx.summary.process_output(&req.out)?; + update_hash(&req.out, &mut ctx.tx_hasher)?; + ctx.advance_next_output_state(review) + } else { + Err(StatusWord::Deny) + } +} + +pub fn handle_sign_tx( + req: SignTxReq, + ctx: TxParsingContext, + review: &mut NbglStreamingReview, +) -> Result<(Response, TxParsingContext), StatusWord> { + let new_ctx = match (req, ctx) { + (SignTxReq::Input(req), TxParsingContext::ParsingInputs(ctx)) => { + handle_input_req(req, ctx)? + } + (SignTxReq::InputCommitment(req), TxParsingContext::ParsingInputCommitments(ctx)) => { + handle_input_commitment_req(req.as_ref(), ctx, review)? + } + (SignTxReq::Output(req), TxParsingContext::ParsingOutputs(ctx)) => { + handle_output_req(req.as_ref(), ctx, review)? + } + (SignTxReq::NextSignature, TxParsingContext::Signing(ctx)) => { + TxParsingContext::Signing(ctx) + } + (SignTxReq::NextSignature, TxParsingContext::Finished) => { + return Err(StatusWord::TxAlreadyFinished) + } + _ => return Err(StatusWord::WrongContext), + }; + + let new_ctx = match new_ctx { + ctx @ (TxParsingContext::ParsingInputs(_) + | TxParsingContext::Finished + | TxParsingContext::ParsingInputCommitments(_) + | TxParsingContext::ParsingOutputs(_)) => ctx, + TxParsingContext::Signing(ctx) => { + let (response, mut new_ctx) = ctx.compute_signature_and_append()?; + new_ctx.show_spinner(); + + return Ok((Response::TxSignature(response), new_ctx)); + } + }; + + Ok((Response::TxNext, new_ctx)) +} + +fn update_hash(data: &T, hasher: &mut Blake2b_512) -> Result<(), StatusWord> { + let mut buf = Vec::::new(); + encode_to(data, &mut buf); + hasher + .update(buf.as_slice()) + .map_err(|_| StatusWord::TxHashFail)?; + Ok(()) +} diff --git a/crates/app-core/src/handlers/sign_tx/summary_collector.rs b/crates/app-core/src/handlers/sign_tx/summary_collector.rs new file mode 100644 index 0000000..8306b4f --- /dev/null +++ b/crates/app-core/src/handlers/sign_tx/summary_collector.rs @@ -0,0 +1,400 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use alloc::collections::BTreeMap; + +use crate::StatusWord; +use mintlayer_messages::{ + mlcp::{ + AccountCommand, AccountSpending, Amount, OrderAccountCommand, OutputValue, TxOutput, H256, + }, + AdditionalOrderInfo, AdditionalUtxoInfo, TxInputWithAdditionalInfo, +}; + +#[derive(Eq, Ord, PartialEq, PartialOrd)] +pub enum CoinOrTokenId { + Coin, + TokenId(H256), +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum TxType { + Transfer, + Burn, + Htlc, + CreateDelegation, + DelegationStake, + DelegationWithdrawal, + CreateStakePool, + DecommissionStakePool, + CreateNft, + CreateToken, + MintTokens, + UnmintTokens, + FreezeToken, + UnfreezeToken, + LockTokenSupply, + ChangeTokenAuthority, + ChangeTokenMetadataUri, + FillOrder, + FreezeOrder, + CreateOrder, + ConcludeOrder, + DataDeposit, + ComplexTransaction, +} + +pub enum InputCommand { + AccountSpending(AccountSpending), + AccountCommand(AccountCommand), + OrderCommand(OrderAccountCommand), +} + +pub struct TxSummaryCollector { + tx_type: Option, + input_command: Option, + total_inputs: BTreeMap, + total_outputs: BTreeMap, +} + +impl TxSummaryCollector { + pub fn new() -> Self { + Self { + tx_type: None, + input_command: None, + total_inputs: BTreeMap::new(), + total_outputs: BTreeMap::new(), + } + } + + pub fn input_command(&self) -> Option<&InputCommand> { + self.input_command.as_ref() + } + + pub fn tx_type(&self) -> Option { + self.tx_type + } + + pub fn total_inputs(&self) -> &BTreeMap { + &self.total_inputs + } + + pub fn total_outputs(&self) -> &BTreeMap { + &self.total_outputs + } + + pub fn fees_iter( + &self, + ) -> impl Iterator> + '_ { + self.total_inputs() + .iter() + .map(move |(coin_or_token, amount)| { + let out = *self + .total_outputs() + .get(coin_or_token) + .unwrap_or(&Amount::ZERO); + + let fee = amount + .into_atoms() + .checked_sub(out.into_atoms()) + .ok_or(StatusWord::TxFeeUnderflow)?; + + Ok((coin_or_token, fee)) + }) + } + + pub fn process_output(&mut self, out: &TxOutput) -> Result<(), StatusWord> { + match &out { + TxOutput::Transfer(value, _) | TxOutput::LockThenTransfer(value, _, _) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::Transfer); + + let (coin_or_token_id, amount) = into_coin_or_token_id_and_amount(value)?; + self.increase_output_totals(coin_or_token_id, amount)?; + } + TxOutput::Burn(value) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::Burn); + + let (coin_or_token_id, amount) = into_coin_or_token_id_and_amount(value)?; + self.increase_output_totals(coin_or_token_id, amount)?; + } + TxOutput::Htlc(value, _) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::Htlc); + + let (coin_or_token_id, amount) = into_coin_or_token_id_and_amount(value)?; + self.increase_output_totals(coin_or_token_id, amount)?; + } + TxOutput::CreateStakePool(_, data) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::CreateStakePool); + + self.increase_output_totals(CoinOrTokenId::Coin, data.pledge)?; + } + TxOutput::ProduceBlockFromStake(_, _) => {} + TxOutput::DelegateStaking(amount, _) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::DelegationStake); + self.increase_output_totals(CoinOrTokenId::Coin, *amount)?; + } + TxOutput::CreateDelegationId(_, _) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::CreateDelegation); + } + TxOutput::IssueFungibleToken(_) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::CreateToken); + } + TxOutput::DataDeposit(_) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::DataDeposit); + } + TxOutput::IssueNft(_, _, _) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::CreateNft); + } + TxOutput::CreateOrder(order_data) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::CreateOrder); + let (coin_or_token_id, amount) = + into_coin_or_token_id_and_amount(&order_data.give)?; + self.increase_output_totals(coin_or_token_id, amount)?; + } + } + + Ok(()) + } + + pub fn process_input(&mut self, inp: &TxInputWithAdditionalInfo) -> Result<(), StatusWord> { + match inp { + TxInputWithAdditionalInfo::Utxo(_, info) => match info { + AdditionalUtxoInfo::UtxoWithPoolData { + utxo: _, + staker_balance, + } => { + self.tx_type = merge_tx_type(self.tx_type, TxType::DecommissionStakePool); + self.increase_input_totals(CoinOrTokenId::Coin, *staker_balance)?; + } + AdditionalUtxoInfo::Utxo(utxo) => { + match &utxo { + TxOutput::Transfer(value, _) + | TxOutput::LockThenTransfer(value, _, _) + | TxOutput::Htlc(value, _) => { + let (coin_or_token_id, amount) = + into_coin_or_token_id_and_amount(value)?; + self.increase_input_totals(coin_or_token_id, amount)?; + } + TxOutput::Burn(_) + | TxOutput::ProduceBlockFromStake(_, _) + | TxOutput::CreateDelegationId(_, _) + | TxOutput::IssueFungibleToken(_) + | TxOutput::DataDeposit(_) + | TxOutput::DelegateStaking(_, _) + | TxOutput::CreateOrder(_) => return Err(StatusWord::TxInvalidInputUtxo), + TxOutput::CreateStakePool(_, data) => { + self.increase_input_totals(CoinOrTokenId::Coin, data.pledge)?; + } + TxOutput::IssueNft(nft_id, _, _) => { + self.increase_input_totals( + CoinOrTokenId::TokenId(*nft_id.hash()), + Amount::from_atoms(1), + )?; + } + }; + } + }, + TxInputWithAdditionalInfo::Account(acc) => { + self.input_command = Some(InputCommand::AccountSpending(acc.spending.clone())); + match acc.spending { + AccountSpending::DelegationBalance(_, amount) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::DelegationWithdrawal); + self.increase_input_totals(CoinOrTokenId::Coin, amount)?; + } + } + } + TxInputWithAdditionalInfo::AccountCommand(_, cmd) => { + self.input_command = Some(InputCommand::AccountCommand(cmd.clone())); + match cmd { + AccountCommand::MintTokens(token_id, amount) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::MintTokens); + self.increase_input_totals( + CoinOrTokenId::TokenId(*token_id.hash()), + *amount, + )?; + } + AccountCommand::ConcludeOrder(_) | AccountCommand::FillOrder(_, _, _) => { + return Err(StatusWord::OrdersV0NotSupported) + } + AccountCommand::UnmintTokens(_) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::UnmintTokens); + } + AccountCommand::LockTokenSupply(_) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::LockTokenSupply); + } + AccountCommand::FreezeToken(_, _) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::FreezeToken); + } + AccountCommand::UnfreezeToken(_) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::UnfreezeToken); + } + AccountCommand::ChangeTokenAuthority(_, _) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::ChangeTokenAuthority); + } + AccountCommand::ChangeTokenMetadataUri(_, _) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::ChangeTokenMetadataUri); + } + } + } + TxInputWithAdditionalInfo::OrderAccountCommand( + cmd, + AdditionalOrderInfo { + initially_asked, + initially_given, + ask_balance, + give_balance, + }, + ) => { + self.input_command = Some(InputCommand::OrderCommand(cmd.clone())); + match cmd { + OrderAccountCommand::FillOrder(_, fill_amount) => { + let (fill_coin_or_token_id, asked_amount) = + into_coin_or_token_id_and_amount(initially_asked)?; + let (given_coin_or_token_id, given_amount) = + into_coin_or_token_id_and_amount(initially_given)?; + + self.increase_output_totals(fill_coin_or_token_id, *fill_amount)?; + + let atoms = given_amount + .into_atoms() + .checked_mul(fill_amount.into_atoms()) + .ok_or(StatusWord::TxNumericOperationFail)? + .checked_div(asked_amount.into_atoms()) + .ok_or(StatusWord::TxNumericOperationFail)?; + let amount = Amount::from_atoms(atoms); + self.increase_input_totals(given_coin_or_token_id, amount)?; + + self.tx_type = merge_tx_type(self.tx_type, TxType::FillOrder); + } + OrderAccountCommand::ConcludeOrder(_) => { + let (coin_or_token_id, _) = + into_coin_or_token_id_and_amount(initially_asked)?; + self.increase_input_totals(coin_or_token_id, *ask_balance)?; + + let (coin_or_token_id, _) = + into_coin_or_token_id_and_amount(initially_given)?; + self.increase_input_totals(coin_or_token_id, *give_balance)?; + + self.tx_type = merge_tx_type(self.tx_type, TxType::ConcludeOrder); + } + OrderAccountCommand::FreezeOrder(_) => { + self.tx_type = merge_tx_type(self.tx_type, TxType::FreezeOrder); + } + } + } + }; + + Ok(()) + } + + fn increase_input_totals( + &mut self, + key: CoinOrTokenId, + amount: Amount, + ) -> Result<(), StatusWord> { + let total = self + .total_inputs + .entry(key) + .or_insert(Amount::from_atoms(0)); + let new_total = total + .into_atoms() + .checked_add(amount.into_atoms()) + .ok_or(StatusWord::TxNumericOperationFail)?; + *total = Amount::from_atoms(new_total); + Ok(()) + } + + fn increase_output_totals( + &mut self, + key: CoinOrTokenId, + amount: Amount, + ) -> Result<(), StatusWord> { + let total = self + .total_outputs + .entry(key) + .or_insert(Amount::from_atoms(0)); + let new_total = total + .into_atoms() + .checked_add(amount.into_atoms()) + .ok_or(StatusWord::TxNumericOperationFail)?; + *total = Amount::from_atoms(new_total); + Ok(()) + } +} + +fn merge_tx_type(tx_type: Option, new_type: TxType) -> Option { + match tx_type { + None => Some(new_type), + // Transfers are a lower priority (as they can be change outputs) so keep the previous type + Some(_) if new_type == TxType::Transfer => tx_type, + Some(_) => Some(TxType::ComplexTransaction), + } +} + +fn into_coin_or_token_id_and_amount( + value: &OutputValue, +) -> Result<(CoinOrTokenId, Amount), StatusWord> { + match value { + OutputValue::Coin(amount) => Ok((CoinOrTokenId::Coin, *amount)), + OutputValue::TokenV1(token_id, amount) => { + Ok((CoinOrTokenId::TokenId(*token_id.hash()), *amount)) + } + } +} + +#[cfg(test)] +mod tests { + use alloc::vec::Vec; + + use crate::testing::prelude::*; + + use mintlayer_messages::mlcp; + + use super::*; + + // TODO: this is a sample test, need to expand it and add more tests + #[test_item] + fn sample_test() { + let mut collector = TxSummaryCollector::new(); + + collector + .process_input(&TxInputWithAdditionalInfo::Utxo( + mlcp::UtxoOutPoint::new( + mlcp::OutPointSourceId::Transaction(mlcp::Id::new(mlcp::H256::zero())), + 0, + ), + AdditionalUtxoInfo::Utxo(mlcp::TxOutput::Transfer( + mlcp::OutputValue::Coin(mlcp::Amount::from_atoms(123)), + mlcp::Destination::AnyoneCanSpend, + )), + )) + .unwrap(); + + collector + .process_output(&mlcp::TxOutput::Transfer( + mlcp::OutputValue::Coin(mlcp::Amount::from_atoms(120)), + mlcp::Destination::AnyoneCanSpend, + )) + .unwrap(); + + let fees = collector + .fees_iter() + .collect::, _>>() + .unwrap(); + assert!(fees == [(&CoinOrTokenId::Coin, 3)]); + } +} diff --git a/crates/app-core/src/handlers/utils.rs b/crates/app-core/src/handlers/utils.rs new file mode 100644 index 0000000..d43404b --- /dev/null +++ b/crates/app-core/src/handlers/utils.rs @@ -0,0 +1,32 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use crate::StatusWord; + +use mintlayer_messages::mlcp::H256; + +use ledger_device_sdk::hash::{blake2::Blake2b_512, HashInit}; + +pub fn mintlayer_hash(data: &[u8]) -> Result { + let mut hasher = Blake2b_512::new(); + let mut message_hash: [u8; 64] = [0u8; 64]; + hasher + .hash(data, &mut message_hash) + .map_err(|_| StatusWord::TxHashFail)?; + + Ok(H256::from_slice(&message_hash[..32])) +} diff --git a/crates/app-core/src/lib.rs b/crates/app-core/src/lib.rs new file mode 100644 index 0000000..19ffc16 --- /dev/null +++ b/crates/app-core/src/lib.rs @@ -0,0 +1,351 @@ +/***************************************************************************** + * + * Mintlayer Ledger App. + * (c) 2023 Ledger SAS. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#![no_std] +// The following is needed to be able to generate a test executable that can be run on speculos. +// 1. Disable the generation of `fn main`. +#![cfg_attr(test, no_main)] +// 2. "custom_test_frameworks" must be enabled to be able to specify the custom runner and use +// the `#[test_case]` attribute (used internally by `testmacro::test_item`). +#![feature(custom_test_frameworks)] +// 3. Specify the custom test runner. All test cases collected by `#[test_case]` will be passed +// to this function. In particular, `sdk_test_runner` will loop over the array of test cases and: +// a) fix references stored inside the test case via pic_rs/pic; +// b) invoke the closure associated with the test case. +#![test_runner(ledger_device_sdk::testing::sdk_test_runner)] +// 4. This will put `fn test_main` at the test crate's root, which will call the runner that we've +// specified above; we'll call it from our `sample_main`. +#![reexport_test_harness_main = "test_main"] + +mod app_ui { + pub mod address; + pub mod menu; + pub mod sign; + pub mod utils; +} +mod handlers { + pub mod get_public_key; + pub mod sign_message; + pub mod sign_tx; + pub mod utils; +} + +mod errors; +#[cfg(test)] +mod testing; + +// Required for using String, Vec, format!... +extern crate alloc; +use alloc::vec::Vec; + +use ledger_device_sdk::{ + io::{ApduHeader, Comm, Reply}, + nbgl::{init_comm, NbglHomeAndSettings, NbglReviewStatus, NbglStreamingReview, StatusType}, +}; + +use app_ui::menu::ui_menu_main; +use errors::sdk_err_to_status; +use handlers::{ + get_public_key::handle_get_public_key, + sign_message::{handle_sign_message, setup_sign_message, SignMessageContext}, + sign_tx::{handle_sign_tx, setup_sign_tx, TxParsingContext}, +}; +use mintlayer_messages::{ + decode_all, encode, Ins, PubKeyP1, Response, SignP1, StatusWord, APDU_CLASS, MAX_ADPU_DATA_LEN, + P2_DONE, P2_MORE, +}; + +pub const MAX_BUFFER_LEN: usize = 4 * MAX_ADPU_DATA_LEN; + +/// Represents a fully assembled Low-Level Instruction. +/// Contains the aggregated data from one or more APDUs (if P2 indicated more data). +pub struct RawInstruction { + pub ins: u8, + pub p1: u8, + pub data: Vec, +} + +pub enum ReceiveInstructionResult { + ExpectingNextChunk, + Instruction(RawInstruction), +} + +/// State machine to handle APDU packet chaining (P2_MORE / P2_DONE). +pub struct ApduTransport { + buffer: Vec, + current_ins: Option, + current_p1: Option, +} + +impl Default for ApduTransport { + fn default() -> Self { + Self { + buffer: Vec::with_capacity(u8::MAX as usize), // Pre-alloc for at least one standard APDU + current_ins: None, + current_p1: None, + } + } +} + +impl ApduTransport { + /// Reads the next APDU from `comm`. + /// + /// - If `P2 == P2_MORE`, it accumulates the data and returns `Ok(None)`. + /// It also sends a `StatusWord::Ok` to the host to request the next chunk. + /// - If `P2 == P2_DONE`, it finishes accumulation and returns `Ok(Some(RawInstruction))`. + pub fn receive(&mut self, comm: &mut Comm) -> Result { + let header: ApduHeader = comm.next_command(); + let data = comm.get_data().map_err(sdk_err_to_status)?; + + // Validation: If we are in the middle of a stream, INS and P1 must match + if let (Some(curr_ins), Some(curr_p1)) = (self.current_ins, self.current_p1) { + if header.ins != curr_ins { + self.reset(); + return Err(StatusWord::WrongInstruction); + } + if header.p1 != curr_p1 { + self.reset(); + return Err(StatusWord::WrongP1P2); + } + } else { + // New command sequence starting + self.current_ins = Some(header.ins); + self.current_p1 = Some(header.p1); + } + + if self.buffer.len() + data.len() > MAX_BUFFER_LEN { + self.reset(); + return Err(StatusWord::MaxBufferLenExceeded); + } + + self.buffer.extend_from_slice(data); + + match header.p2 { + P2_MORE => Ok(ReceiveInstructionResult::ExpectingNextChunk), + P2_DONE => { + // Construct the full instruction + let raw = RawInstruction { + ins: header.ins, + p1: header.p1, + data: core::mem::take(&mut self.buffer), + }; + self.reset(); + Ok(ReceiveInstructionResult::Instruction(raw)) + } + _ => { + self.reset(); + Err(StatusWord::WrongP1P2) + } + } + } + + fn reset(&mut self) { + self.buffer.clear(); + self.current_ins = None; + self.current_p1 = None; + } +} + +pub enum Command { + GetPubkey { p1: PubKeyP1, data: Vec }, + SignTx { p1: SignP1, data: Vec }, + SignMessage { p1: SignP1, data: Vec }, + Ping, +} + +impl TryFrom for Command { + type Error = StatusWord; + + fn try_from(raw: RawInstruction) -> Result { + match raw.ins { + Ins::PUB_KEY => { + let p1: PubKeyP1 = raw.p1.try_into()?; + Ok(Command::GetPubkey { p1, data: raw.data }) + } + Ins::SIGN_TX => { + let p1: SignP1 = raw.p1.try_into()?; + Ok(Command::SignTx { p1, data: raw.data }) + } + Ins::SIGN_MSG => { + let p1: SignP1 = raw.p1.try_into()?; + Ok(Command::SignMessage { p1, data: raw.data }) + } + Ins::PING => Ok(Command::Ping), + _ => Err(StatusWord::InsNotSupported), + } + } +} + +fn show_status_and_home_if_needed(cmd: &Command, ctx: &mut AppContext, status: &StatusWord) { + let (show_status, status_type) = match (cmd, status) { + (Command::GetPubkey { p1, .. }, StatusWord::Deny | StatusWord::Ok) if p1.display() => { + (true, StatusType::Address) + } + (Command::SignTx { .. }, StatusWord::Deny | StatusWord::Ok) if ctx.finished() => { + (true, StatusType::Transaction) + } + (Command::SignMessage { .. }, StatusWord::Deny | StatusWord::Ok) if ctx.finished() => { + (true, StatusType::Message) + } + (Command::Ping, StatusWord::Ok) => { + ctx.home.show_and_return(); + return; + } + (_, _) => (false, StatusType::Transaction), // Default fallback + }; + + if show_status { + let success = *status == StatusWord::Ok; + NbglReviewStatus::new() + .status_type(status_type) + .show(success); + + // call home.show_and_return() to show home and setting screen + ctx.home.show_and_return(); + } +} + +pub enum DataContext { + TxContext(TxParsingContext, NbglStreamingReview), + SignMessageContext(SignMessageContext), +} + +struct AppContext { + pub data_context: Option, + pub home: NbglHomeAndSettings, +} + +impl AppContext { + fn new() -> Self { + Self { + data_context: None, + home: Default::default(), + } + } + + fn finished(&self) -> bool { + self.data_context.as_ref().is_some_and(|ctx| match ctx { + DataContext::SignMessageContext(ctx) => ctx.finished(), + DataContext::TxContext(ctx, _) => ctx.finished(), + }) + } +} + +pub fn mintlayer_main() { + let mut comm = Comm::new().set_expected_cla(APDU_CLASS); + + let mut tx_ctx = AppContext::new(); + + // Initialize reference to Comm instance for NBGL API calls. + init_comm(&mut comm); + tx_ctx.home = ui_menu_main(); + tx_ctx.home.show_and_return(); + + let mut transport = ApduTransport::default(); + + loop { + let raw_instruction = match transport.receive(&mut comm) { + Ok(ReceiveInstructionResult::Instruction(raw)) => raw, + Ok(ReceiveInstructionResult::ExpectingNextChunk) => { + // Signal host that we received the chunk and are waiting for more + comm.append(&encode(Response::ExpectingNextChunk)); + comm.reply(Reply(StatusWord::Ok as u16)); + continue; // Waiting for more chunks, loop around + } + Err(sw) => { + comm.reply(Reply(sw as u16)); + continue; + } + }; + + let command = match Command::try_from(raw_instruction) { + Ok(cmd) => cmd, + Err(sw) => { + comm.reply(Reply(sw as u16)); + continue; + } + }; + + let status = match handle_command(&command, &mut tx_ctx) { + Ok(response) => { + comm.append(&encode(response)); + comm.reply_ok(); + StatusWord::Ok + } + Err(sw) => { + comm.reply(Reply(sw as u16)); + sw + } + }; + + show_status_and_home_if_needed(&command, &mut tx_ctx, &status); + } +} + +fn handle_command(cmd: &Command, ctx: &mut AppContext) -> Result { + match cmd { + Command::GetPubkey { p1, data } => { + let req = decode_all(data).ok_or(StatusWord::DeserializeFail)?; + handle_get_public_key(req, p1.display()).map(Response::PublicKey) + } + Command::SignTx { p1, data } => match p1 { + SignP1::Start => { + let req = decode_all(data).ok_or(StatusWord::DeserializeFail)?; + ctx.data_context = Some(setup_sign_tx(req)?); + Ok(Response::TxSetup) + } + SignP1::Next => { + let (mut tx_ctx, mut review) = match ctx.data_context.take() { + Some(DataContext::TxContext(c, r)) => (c, r), + _ => return Err(StatusWord::WrongContext), + }; + + let req = decode_all(data).ok_or(StatusWord::DeserializeFail)?; + + tx_ctx.show_spinner(); + + match handle_sign_tx(req, tx_ctx, &mut review) { + Ok((response, new_ctx)) => { + ctx.data_context = Some(DataContext::TxContext(new_ctx, review)); + Ok(response) + } + Err(sw) => { + ctx.data_context = None; + Err(sw) + } + } + } + }, + Command::SignMessage { p1, data } => match p1 { + SignP1::Start => { + let req = decode_all(data).ok_or(StatusWord::DeserializeFail)?; + ctx.data_context = Some(setup_sign_message(req)); + Ok(Response::MessageSetup) + } + SignP1::Next => { + let msg_ctx = match ctx.data_context.as_mut() { + Some(DataContext::SignMessageContext(ctx)) => ctx, + _ => return Err(StatusWord::WrongContext), + }; + handle_sign_message(data, msg_ctx).map(Response::MessageSignature) + } + }, + Command::Ping => Ok(Response::Pong), + } +} diff --git a/crates/app-core/src/testing.rs b/crates/app-core/src/testing.rs new file mode 100644 index 0000000..8b75de4 --- /dev/null +++ b/crates/app-core/src/testing.rs @@ -0,0 +1,47 @@ +/***************************************************************************** + * + * Mintlayer Ledger App. + * (c) 2023 Ledger SAS. + * (c) 2026 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +use alloc::{borrow::ToOwned as _, format}; + +pub mod prelude { + // testmacro::test_item expects `TestType` to be imported. + pub use ledger_device_sdk::testing::TestType; + + pub use testmacro::test_item; +} + +#[no_mangle] +extern "C" fn sample_main() { + crate::test_main(); + ledger_device_sdk::exit_app(0); +} + +#[panic_handler] +fn handle_panic(info: &core::panic::PanicInfo) -> ! { + ledger_device_sdk::error!( + "Panic occurred at {}: {}", + info.location().map_or_else( + || "???".to_owned(), + |loc| format!("{}:{}", loc.file(), loc.line()) + ), + info.message(), + ); + + ledger_device_sdk::exit_app(1); +} diff --git a/crates/messages/Cargo.toml b/crates/messages/Cargo.toml new file mode 100644 index 0000000..03edaeb --- /dev/null +++ b/crates/messages/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "mintlayer-messages" +version.workspace = true +edition = "2024" + +[dependencies] +derive_more = { workspace = true, default-features = false, features = ["display"]} +num_enum = { workspace = true, default-features = false } +# Note: normally we would enable the "chain-error" feature of parity-scale-codec to make decode errors +# more informative. But in the Ledger app we never examine or even print those errors, so enabling this +# feature would only increase the size of the binary and make the app use more stack during decoding. +parity-scale-codec = { workspace = true, default-features = false, features = ["derive"] } + +mintlayer-core-primitives.workspace = true + +[lib] +# Note: this crate doesn't have unit tests at the moment. If we ever need them, a custom runner +# has to be set up the same way it's done in `mintlayer-app-core`. For now we just disable tests +# completely to prevent Cargo from producing an uncompilable test binary. +test = false diff --git a/crates/messages/src/lib.rs b/crates/messages/src/lib.rs new file mode 100644 index 0000000..7bf1498 --- /dev/null +++ b/crates/messages/src/lib.rs @@ -0,0 +1,503 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#![no_std] + +// Required for using String, Vec, format!... +extern crate alloc; + +use alloc::{boxed::Box, vec::Vec}; +use core::iter::ExactSizeIterator; + +use derive_more::Display; +use num_enum::{IntoPrimitive, TryFromPrimitive}; +use parity_scale_codec::{Decode, DecodeAll}; + +pub use mintlayer_core_primitives as mlcp; +pub use parity_scale_codec::Encode; + +pub const APDU_CLASS: u8 = 0xE1; +pub const MAX_ADPU_DATA_LEN: usize = u8::MAX as usize; + +// P2 is used to indicate APDU chunking. +// `P2_DONE` marks the final chunk, while `P2_MORE` indicates that more chunks follow. +pub const P2_DONE: u8 = 0x00; +pub const P2_MORE: u8 = 0x80; + +fn wrong_p1p2(_: u8) -> StatusWord { + StatusWord::WrongP1P2 +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] +#[num_enum(error_type(name = StatusWord, constructor = wrong_p1p2))] +#[repr(u8)] +pub enum PubKeyP1 { + NoDisplayAddress = 0, + DisplayAddress = 1, +} + +impl PubKeyP1 { + pub fn display(&self) -> bool { + *self == Self::DisplayAddress + } +} + +pub struct Ins {} + +impl Ins { + pub const PUB_KEY: u8 = 0x00; + pub const SIGN_TX: u8 = 0x01; + pub const SIGN_MSG: u8 = 0x02; + pub const PING: u8 = 0x03; +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] +#[num_enum(error_type(name = StatusWord, constructor = wrong_p1p2))] +#[repr(u8)] +pub enum SignP1 { + Start = 0, + Next = 1, +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] +#[num_enum(error_type(name = StatusWord, constructor = wrong_p1p2))] +#[repr(u8)] +pub enum PingP1 { + Start = 0, +} + +#[derive(Encode, Decode)] +pub struct PublicKeyReq { + pub coin_type: CoinType, + pub path: Bip32Path, +} + +#[derive(Encode, Decode)] +pub struct SignMessageReq { + pub coin: CoinType, + pub addr_type: AddrType, + pub path: Bip32Path, +} + +#[derive(Encode, Decode)] +pub enum SignTxReq { + Input(Box), + InputCommitment(Box), + Output(Box), + NextSignature, +} + +#[derive(Encode, Decode)] +pub struct TxMetadataV1Req { + pub num_inputs: u32, + pub num_outputs: u32, +} + +#[derive(Encode, Decode)] +pub enum TxMetadataVersionReq { + V1(TxMetadataV1Req), +} + +#[derive(Encode, Decode)] +pub struct TxMetadataReq { + pub coin: CoinType, + pub version: TxMetadataVersionReq, +} + +#[derive(Encode, Decode)] +pub struct TxInputReq { + pub addresses: Vec, + pub inp: TxInputWithAdditionalInfo, +} + +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +pub struct AdditionalOrderInfo { + pub initially_asked: mlcp::OutputValue, + pub initially_given: mlcp::OutputValue, + pub ask_balance: mlcp::Amount, + pub give_balance: mlcp::Amount, +} + +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +pub enum AdditionalUtxoInfo { + Utxo(mlcp::TxOutput), + UtxoWithPoolData { + utxo: mlcp::TxOutput, + staker_balance: mlcp::Amount, + }, +} + +impl From for mlcp::SighashInputCommitment { + fn from(value: AdditionalUtxoInfo) -> Self { + match value { + AdditionalUtxoInfo::Utxo(output) => mlcp::SighashInputCommitment::Utxo(output), + AdditionalUtxoInfo::UtxoWithPoolData { + utxo, + staker_balance, + } => mlcp::SighashInputCommitment::ProduceBlockFromStakeUtxo { + utxo, + staker_balance, + }, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +pub enum TxInputWithAdditionalInfo { + #[codec(index = 0)] + Utxo(mlcp::UtxoOutPoint, AdditionalUtxoInfo), + + #[codec(index = 1)] + Account(mlcp::AccountOutPoint), + + #[codec(index = 2)] + AccountCommand(mlcp::AccountNonce, mlcp::AccountCommand), + + #[codec(index = 3)] + OrderAccountCommand(mlcp::OrderAccountCommand, AdditionalOrderInfo), +} + +impl TxInputWithAdditionalInfo { + pub fn into_input_and_commitment(self) -> (mlcp::TxInput, mlcp::SighashInputCommitment) { + match self { + TxInputWithAdditionalInfo::Utxo(utxo, info) => (mlcp::TxInput::Utxo(utxo), info.into()), + TxInputWithAdditionalInfo::Account(acc) => ( + mlcp::TxInput::Account(acc), + mlcp::SighashInputCommitment::None, + ), + TxInputWithAdditionalInfo::AccountCommand(nonce, cmd) => ( + mlcp::TxInput::AccountCommand(nonce, cmd), + mlcp::SighashInputCommitment::None, + ), + TxInputWithAdditionalInfo::OrderAccountCommand(cmd, info) => { + let commitment = match &cmd { + mlcp::OrderAccountCommand::FillOrder(_, _) => { + mlcp::SighashInputCommitment::FillOrderAccountCommand { + initially_asked: info.initially_asked, + initially_given: info.initially_given, + } + } + mlcp::OrderAccountCommand::ConcludeOrder(_) => { + mlcp::SighashInputCommitment::ConcludeOrderAccountCommand { + initially_asked: info.initially_asked, + initially_given: info.initially_given, + ask_balance: info.ask_balance, + give_balance: info.give_balance, + } + } + mlcp::OrderAccountCommand::FreezeOrder(_) => mlcp::SighashInputCommitment::None, + }; + (mlcp::TxInput::OrderAccountCommand(cmd), commitment) + } + } + } +} + +#[derive(Encode, Decode)] +pub struct TxOutputReq { + pub out: mlcp::TxOutput, +} + +#[derive(Encode, Decode, Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive)] +#[repr(u8)] +pub enum CoinType { + Mainnet = 0, + Testnet = 1, + Regtest = 2, + Signet = 3, +} + +impl From for mlcp::CoinType { + fn from(value: CoinType) -> Self { + match value { + CoinType::Mainnet => Self::Mainnet, + CoinType::Testnet => Self::Testnet, + CoinType::Regtest => Self::Regtest, + CoinType::Signet => Self::Signet, + } + } +} + +#[repr(u8)] +#[derive(Encode, Decode, Clone, Copy, IntoPrimitive)] +pub enum AddrType { + PublicKey = 0, + PublicKeyHash = 1, +} + +/// BIP32 path stored as an array of [`u32`]. +#[derive(Default, Encode, Decode, Clone)] +pub struct Bip32Path(pub Vec); + +impl AsRef<[u32]> for Bip32Path { + fn as_ref(&self) -> &[u32] { + &self.0 + } +} + +/// Address path to be signed for an input +#[derive(Encode, Decode)] +pub struct InputAddressPath { + pub path: Bip32Path, + pub multisig_idx: Option, +} + +#[derive(Encode, Decode)] +pub struct PublicKey(pub [u8; 65]); + +#[derive(Encode, Decode)] +pub struct ChainCode(pub [u8; 32]); + +#[derive(Encode, Decode)] +pub struct GetPublicKeyResponse { + pub public_key: PublicKey, + pub chain_code: ChainCode, +} + +#[derive(Encode, Decode)] +pub struct SignatureResponse(pub [u8; 64]); + +#[derive(Encode, Decode)] +pub struct TxInputSignatureResponse { + pub signature: SignatureResponse, + pub input_idx: u32, + pub multisig_idx: Option, + pub has_next: bool, +} + +#[derive(Encode, Decode)] +pub struct MsgSignatureResponse { + pub signature: SignatureResponse, +} + +#[derive(Encode, Decode)] +pub enum Response { + #[codec(index = 0)] + ExpectingNextChunk, + #[codec(index = 1)] + PublicKey(GetPublicKeyResponse), + #[codec(index = 2)] + TxSetup, + #[codec(index = 3)] + TxNext, + #[codec(index = 4)] + TxSignature(TxInputSignatureResponse), + #[codec(index = 5)] + MessageSetup, + #[codec(index = 6)] + MessageSignature(MsgSignatureResponse), + #[codec(index = 7)] + Pong, +} + +pub fn encode(t: T) -> Vec { + t.encode() +} + +pub fn encode_to(t: T, buf: &mut Vec) { + t.encode_to(buf) +} + +pub fn decode_all(mut bytes: &[u8]) -> Option { + T::decode_all(&mut bytes).ok() +} + +pub fn encode_as_compact(num: u32) -> Vec { + parity_scale_codec::Compact::::encode(&num.into()) +} + +/// This represents an APDU used in communication with Mintlayer Ledger app. +/// +/// Note that the class byte is not present here, because it's the same for all our APDUs. +/// +/// Also, we don't have the second parameter byte here either, because its meaning is the same +/// across all APDUs - it specifies whether this APDU represents the last chunk of the instruction. +pub struct Apdu<'a> { + instruction_byte: u8, + param1_byte: u8, + command_data: &'a [u8], + is_last_chunk: bool, +} + +impl<'a> Apdu<'a> { + /// Create an APDU with data; this will fail if the data length exceeds the allowed maximum. + pub fn new_with_data( + instruction_byte: u8, + param1_byte: u8, + command_data: &'a [u8], + ) -> Option { + (command_data.len() <= MAX_ADPU_DATA_LEN).then_some(Self { + instruction_byte, + param1_byte, + command_data, + is_last_chunk: true, + }) + } + + /// Returns an ExactSizeIterator of APDUs by chunking the data to MAX_ADPU_DATA_LEN + pub fn new_chunks( + instruction_byte: u8, + param1_byte: u8, + data: &'a [u8], + ) -> impl ExactSizeIterator { + let chunk_iter = data.chunks(MAX_ADPU_DATA_LEN); + let last_chunk_idx = chunk_iter.len() - 1; + + chunk_iter.enumerate().map(move |(chunk_idx, chunk)| Self { + instruction_byte, + param1_byte, + command_data: chunk, + is_last_chunk: chunk_idx == last_chunk_idx, + }) + } + + pub fn is_last(&self) -> bool { + self.is_last_chunk + } + + /// The number of bytes that will be written by `write_bytes`. + /// + /// This can be used to reserve the required capacity in the destination collection + /// (note that `Extend::extend_reserve is` still nightly-only, so we can't use it). + pub fn bytes_count(&self) -> usize { + // class, instruction, param1 and param2 bytes, then 1 byte for data length, then the + // data itself. + 5 + self.command_data.len() + } + + pub fn write_bytes(&self, collection: &mut impl core::iter::Extend) { + let param2_byte = if self.is_last_chunk { P2_DONE } else { P2_MORE }; + + collection.extend([ + APDU_CLASS, + self.instruction_byte, + self.param1_byte, + param2_byte, + ]); + // Should be true by construction + assert!(self.command_data.len() <= u8::MAX as usize); + collection.extend(core::iter::once(self.command_data.len() as u8)); + collection.extend(self.command_data.iter().copied()); + } +} + +/// Application status words. +#[repr(u16)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Display, IntoPrimitive, TryFromPrimitive)] +pub enum StatusWord { + // Standard Ledger APDU Codes + #[display("Success")] + Ok = 0x9000, + #[display("Nothing received")] + NothingReceived = 0x6982, + #[display("User cancelled")] + Deny = 0x6985, + #[display("CLA not supported")] + ClaNotSupported = 0x6E00, + #[display("Instruction not supported")] + InsNotSupported = 0x6E01, + #[display("Wrong P1/P2 parameters")] + WrongP1P2 = 0x6E02, + #[display("Wrong APDU length")] + WrongApduLength = 0x6E03, + #[display("Unknown")] + Unknown = 0x6D00, + #[display("Panic")] + Panic = 0xE000, + #[display("Device locked")] + DeviceLocked = 0x5515, + + // App Specific Errors (0xB...) + #[display("Transaction display failed")] + TxDisplayFail = 0xB000, + #[display("Transaction lock time value is invalid")] + TxLockTimeInvalid = 0xB001, + #[display("Transaction wrong length")] + TxWrongLength = 0xB002, + #[display("Transaction hashing failed")] + TxHashFail = 0xB003, + #[display("Transaction address failed")] + TxAddressFail = 0xB004, + #[display("Different instruction than expected")] + WrongInstruction = 0xB005, + #[display("Key derivation failed")] + KeyDeriveFail = 0xB006, + #[display("Orders V0 not supported")] + OrdersV0NotSupported = 0xB007, + #[display("Wrong context")] + WrongContext = 0xB008, + #[display("Deserialization failed")] + DeserializeFail = 0xB009, + #[display("Invalid input UTXO")] + TxInvalidInputUtxo = 0xB00A, + #[display("Numeric operation failed")] + TxNumericOperationFail = 0xB00B, + #[display("Tx fee underflow")] + TxFeeUnderflow = 0xB00C, + #[display("Invalid input path")] + TxInvalidInputPath = 0xB00D, + #[display("Nothing to sign")] + NothingToSign = 0xB00E, + #[display("Transaction already finished")] + TxAlreadyFinished = 0xB00F, + #[display("Invalid path")] + InvalidPath = 0xB010, + #[display("Invalid uncompressed public key")] + InvalidUncompressedPublicKey = 0xB011, + #[display("Max buffer length exceeded")] + MaxBufferLenExceeded = 0xB012, + #[display("Different input commitment hash")] + DifferentInputCommitmentHash = 0xB013, + #[display("Invalid Timestamp")] + InvalidTimestamp = 0xB014, + + // Ecc Errors + #[display("ECC Carry")] + EccCarry = 0xB100, + #[display("ECC Locked")] + EccLocked = 0xB101, + #[display("ECC Unlocked")] + EccUnlocked = 0xB102, + #[display("ECC Not Locked")] + EccNotLocked = 0xB103, + #[display("ECC Not Unlocked")] + EccNotUnlocked = 0xB104, + #[display("ECC Internal Error")] + EccInternalError = 0xB105, + #[display("ECC Invalid Parameter Size")] + EccInvalidParameterSize = 0xB106, + #[display("ECC Invalid Parameter Value")] + EccInvalidParameterValue = 0xB107, + #[display("ECC Invalid Parameter")] + EccInvalidParameter = 0xB108, + #[display("ECC Not Invertible")] + EccNotInvertible = 0xB109, + #[display("ECC Overflow")] + EccOverflow = 0xB10A, + #[display("ECC Memory Full")] + EccMemoryFull = 0xB10B, + #[display("ECC No Residue")] + EccNoResidue = 0xB10C, + #[display("ECC Point At Infinity")] + EccPointAtInfinity = 0xB10D, + #[display("ECC Invalid Point")] + EccInvalidPoint = 0xB10E, + #[display("ECC Invalid Curve")] + EccInvalidCurve = 0xB10F, + #[display("ECC Generic Error")] + EccGenericError = 0xB110, +} diff --git a/doc/mintlayer.md b/doc/mintlayer.md new file mode 100644 index 0000000..9dd23d9 --- /dev/null +++ b/doc/mintlayer.md @@ -0,0 +1,277 @@ +# Mintlayer application: Technical Specifications + +This page details the protocol implemented for the Mintlayer Ledger app. + +## Framework + +### APDUs + +The messaging format of the app is compatible with the standard [APDU protocol](https://developers.ledger.com/docs/device-app/explanation/io#apdu-interpretation-loop). + +The class byte used for all standard commands is `CLA = 0xE1`. + +| CLA | INS | COMMAND NAME | DESCRIPTION | +| --- | --- | -------------- | ------------------------------------------------------------------ | +| E1 | 00 | GET_PUBLIC_KEY | Return (and optionally show on screen) a public key and chain code | +| E1 | 01 | SIGN_TX | Sign a transaction through a multi-step process | +| E1 | 02 | SIGN_MSG | Sign a generic message | +| E1 | 03 | PING | Simple ping request to check connectivity | + +### Chunking and P2 + +The APDU buffer on the Ledger device has a maximum data length (`MAX_ADPU_DATA_LEN` = 255 bytes). To accommodate larger payloads, the app implements a chunking mechanism controlled by the `P2` parameter: + +- `P2 = 0x00` (`P2_DONE`): This is the final chunk (or the only chunk) of the instruction. The app will assemble the buffer and execute the command. +- `P2 = 0x80` (`P2_MORE`): More chunks follow. The app accumulates the data into a buffer (up to a maximum of `1020` bytes) and returns `0x9000` (Success) to ask the client for the next chunk. + +_Note: For chunked commands, `INS` and `P1` must remain identical across all chunks of the same sequence._ + +### Data Serialization and Responses + +The app uses **SCALE codec** (`parity_scale_codec`) for the serialization and deserialization of the data payloads. Vector length prefixes and standard variable-length integer types are represented using SCALE's Compact encoding. + +#### Response Wrapper + +On a successful command execution (returning status word `0x9000`), the app encodes the returned payload inside a top-level SCALE-encoded `Response` enum. + +The SCALE representation of an enum begins with a single byte representing the variant index, followed by the encoded fields of that variant. + +The `Response` enum structure and its variant indices are: + +| Variant Index | Variant Name | Inner Payload Type | Description | +|---|---|---|---| +| `0` | `ExpectingNextChunk` | None | Returned when more APDU chunks are expected (`P2_MORE` sequence) | +| `1` | `PublicKey` | `GetPublicKeyResponse` | Public key and chain code response | +| `2` | `TxSetup` | None | Acknowledges transaction initialization (`SIGN_TX` with `P1 = 0`) | +| `3` | `TxNext` | None | Acknowledges receipt of a transaction chunk | +| `4` | `TxSignature` | `TxInputSignatureResponse` | Contains an input signature | +| `5` | `MessageSetup` | None | Acknowledges message signing initialization (`SIGN_MSG` with `P1 = 0`) | +| `6` | `MessageSignature` | `MsgSignatureResponse` | Contains the final message signature | +| `7` | `Pong` | None | Pong response for the `PING` instruction | + +Any successful command output described below is prefixed by its corresponding 1-byte variant index. + +## Status Words + +The application returns standard Ledger status words as well as app-specific and ECC cryptographic errors. + +| SW | SW name | Description | +| ------ | ------------------------------ | ---------------------------------------------- | +| 0x5515 | `DeviceLocked` | Device locked | +| 0x6982 | `NothingReceived` | Nothing received | +| 0x6985 | `Deny` | Rejected by user / User cancelled | +| 0x6D00 | `Unknown` | Unknown | +| 0x6E00 | `ClaNotSupported` | CLA not supported | +| 0x6E01 | `InsNotSupported` | Instruction not supported | +| 0x6E02 | `WrongP1P2` | Wrong P1/P2 parameters | +| 0x6E03 | `WrongApduLength` | Wrong APDU length | +| 0x9000 | `Ok` | Success | +| 0xB000 | `TxDisplayFail` | Transaction display failed | +| 0xB001 | `TxLockTimeInvalid` | Transaction lock time value is invalid | +| 0xB002 | `TxWrongLength` | Transaction wrong length | +| 0xB003 | `TxHashFail` | Transaction hashing failed | +| 0xB004 | `TxAddressFail` | Transaction address failed | +| 0xB005 | `WrongInstruction` | Different instruction than expected | +| 0xB006 | `KeyDeriveFail` | Key derivation failed | +| 0xB007 | `OrdersV0NotSupported` | Orders V0 not supported | +| 0xB008 | `WrongContext` | Wrong context (e.g., Next called before Start) | +| 0xB009 | `DeserializeFail` | SCALE deserialization failed | +| 0xB00A | `TxInvalidInputUtxo` | Invalid input UTXO | +| 0xB00B | `TxNumericOperationFail` | Numeric operation failed | +| 0xB00C | `TxFeeUnderflow` | Tx fee underflow | +| 0xB00D | `TxInvalidInputPath` | Invalid input path | +| 0xB00E | `NothingToSign` | Nothing to sign | +| 0xB00F | `TxAlreadyFinished` | Transaction already finished | +| 0xB010 | `InvalidPath` | Invalid BIP32 path | +| 0xB011 | `InvalidUncompressedPublicKey` | Invalid uncompressed public key | +| 0xB012 | `MaxBufferLenExceeded` | Max buffer length exceeded (Chunking limit) | +| 0xB013 | `DifferentInputCommitmentHash` | Different input commitment hash | +| 0xB014 | `InvalidTimestamp` | Invalid Timestamp | +| 0xB100 | `EccCarry` | ECC Carry | +| 0xB101 | `EccLocked` | ECC Locked | +| 0xB102 | `EccUnlocked` | ECC Unlocked | +| 0xB103 | `EccNotLocked` | ECC Not Locked | +| 0xB104 | `EccNotUnlocked` | ECC Not Unlocked | +| 0xB105 | `EccInternalError` | ECC Internal Error | +| 0xB106 | `EccInvalidParameterSize` | ECC Invalid Parameter Size | +| 0xB107 | `EccInvalidParameterValue` | ECC Invalid Parameter Value | +| 0xB108 | `EccInvalidParameter` | ECC Invalid Parameter | +| 0xB109 | `EccNotInvertible` | ECC Not Invertible | +| 0xB10A | `EccOverflow` | ECC Overflow | +| 0xB10B | `EccMemoryFull` | ECC Memory Full | +| 0xB10C | `EccNoResidue` | ECC No Residue | +| 0xB10D | `EccPointAtInfinity` | ECC Point At Infinity | +| 0xB10E | `EccInvalidPoint` | ECC Invalid Point | +| 0xB10F | `EccInvalidCurve` | ECC Invalid Curve | +| 0xB110 | `EccGenericError` | ECC Generic Error | +| 0xE000 | `Panic` | Panic | + +--- + +## Commands + +### GET_PUBLIC_KEY + +Returns a public key and chain code at the given derivation path. +Optionally displays the generated address on the device screen for user verification. + +#### Encoding + +**Command** + +| _CLA_ | _INS_ | _P1_ | +| ----- | ----- | -------------------- | +| E1 | 00 | `0` or `1` (Display) | + +**Input data (`PublicKeyReq` - SCALE encoded)** + +| Type | Name | Description | +| ----------- | ----------- | --------------------------------------------------------- | +| `u8` (Enum) | `coin_type` | `0` = Mainnet, `1` = Testnet, `2` = Regtest, `3` = Signet | +| `Vec` | `path` | The BIP32 derivation path | + +**Output data (`Response::PublicKey(GetPublicKeyResponse)` - SCALE encoded)** + +| Length | Description | +| ------ | ------------------------------------------------------------------- | +| `1` | Variant index byte (`0x01`) | +| `65` | The uncompressed public key (`GetPublicKeyResponse.public_key`) | +| `32` | The chain code (`GetPublicKeyResponse.chain_code`) | + +#### Description + +If `P1` is `0`, the application derives the public key and returns it silently. +If `P1` is `1`, the application will display the address derived from the requested path on the device screen. +The command will only return `Ok` (0x9000) if the user approves it, otherwise, it returns `Deny` (0x6985). + +--- + +### SIGN_TX + +Signs a Mintlayer transaction. +Because transactions can be larger than available APDU buffers and RAM, the parsing and signing process is split into an interactive state machine using `P1 = 0` (Start) and `P1 = 1` (Next). + +#### Encoding + +**Command** + +| _CLA_ | _INS_ | _P1_ | +| ----- | ----- | ------------------------- | +| E1 | 01 | `0` (Start) or `1` (Next) | + +**Input Data for `P1 = 0` (Start) (`TxMetadataReq` - SCALE encoded)** + +| Type | Name | Description | +| ----- | ------------- | --------------------------------------------------------- | +| `u8` | `coin` | `0` = Mainnet, `1` = Testnet, `2` = Regtest, `3` = Signet | +| `u8` | `version` | Transaction version | +| `u32` | `num_inputs` | Total number of inputs in the transaction | +| `u32` | `num_outputs` | Total number of outputs in the transaction | + +**Input Data for `P1 = 1` (Next) (`SignTxReq` Enum - SCALE encoded)** + +The client sends a sequence of `SignTxReq` variants. The variant index dictates the type of data being sent: + +- `Input` (Index 0): Contains `TxInputReq` (Input address paths and UTXO/Account info). +- `InputCommitment` (Index 1): Contains `SighashInputCommitment`. +- `Output` (Index 2): Contains `TxOutputReq`. +- `NextSignature` (Index 3): Requests the device to yield the next available signature. + +**Output data (`Response::TxSignature(TxInputSignatureResponse)` - SCALE encoded)** + +Yielded during `NextSignature` sequences. + +The response payload is prefixed with the `TxSignature` variant index (`0x04`), followed by the `TxInputSignatureResponse` fields: + +| Type | Name | Description | +| ------------- | -------------- | ------------------------------------------- | +| `[u8; 64]` | `signature` | The 64-byte cryptographic signature | +| `Option` | `multisig_idx` | Optional multisig index | +| `u32` | `input_idx` | The index of the input that was just signed | +| `bool` | `has_next` | True if there are more signatures remaining | + +*Note: For `Start` (`P1 = 0`) and intermediate `Next` (`P1 = 1`) data chunks (before signatures), the app returns `Response::TxSetup` (variant index `0x02`) and `Response::TxNext` (variant index `0x03`) respectively, with no extra fields.* + +#### Description + +To sign a transaction, the client must follow a strict order: + +1. Call `SIGN_TX` with `P1 = 0` (Start) passing the overall transaction metadata (`TxMetadataReq`). +2. Sequentially call `SIGN_TX` with `P1 = 1` (Next) to stream inputs `Input`, input commitments `InputCommitment` and then outputs (`Output`). +3. After all data is verified by the user on the device's secure screen, the client requests signatures by repeatedly calling `SIGN_TX` with `P1 = 1` and the `NextSignature` variant. +4. The device will yield `TxInputSignatureResponse` payloads until `has_next` is false. + +--- + +### SIGN_MSG + +Signs a generic message using a BIP-32 derived key. The process is stateful to allow streaming long messages. + +#### Encoding + +**Command** + +| _CLA_ | _INS_ | _P1_ | +| ----- | ----- | ------------------------- | +| E1 | 02 | `0` (Start) or `1` (Next) | + +**Input Data for `P1 = 0` (Start) (`SignMessageReq` - SCALE encoded)** + +| Type | Name | Description | +| ----------- | ----------- | --------------------------------------------- | +| `u8` (Enum) | `coin` | Coin type (Mainnet, Testnet, Regtest, Signet) | +| `u8` (Enum) | `addr_type` | `0` = PublicKey, `1` = PublicKeyHash | +| `Vec` | `path` | The BIP32 derivation path to use for signing | + +**Input Data for `P1 = 1` (Next)** + +| Type | Description | +| ------------ | ------------------------------------------------------------- | +| `` | The raw byte chunks of the message payload to be accumulated. | + +**Output data (`Response::MessageSignature(MsgSignatureResponse)` - SCALE encoded)** + +The response payload is prefixed with the `MessageSignature` variant index (`0x06`), followed by the `MsgSignatureResponse` fields: + +| Length | Description | +| ------ | ----------------------------------- | +| `64` | The 64-byte cryptographic signature | + +*Note: For `Start` (`P1 = 0`) initialization, the app returns `Response::MessageSetup` (variant index `0x05`) with no extra fields.* + +#### Description + +The `SIGN_MSG` flow initializes the signing context via `Start`. +The client then sends the message chunks iteratively using `Next`. +Once the message transmission is completed and the user validates the request on the hardware screen, +the device returns the 64-byte signature. +Chunking the payload via the `P2` parameter mechanism is utilized here if the data exceeds a single APDU packet limit. + +--- + +### PING + +Simple ping request to check connectivity. + +#### Encoding + +**Command** + +| _CLA_ | _INS_ | _P1_ | +| ----- | ----- | ---- | +| E1 | 03 | `0` | + +**Input data** + +None. + +**Output data (`Response::Pong` - SCALE encoded)** + +| Length | Description | +| ------ | ----------------------------------------------------------- | +| `1` | Variant index byte (`0x07`) representing `Response::Pong` | + +#### Description + +The client sends a `PING` command to verify that the app is running and responsive. +The app returns `Response::Pong` (success indicator) on success, and returns the home screen to the user. diff --git a/docs/memory_usage.md b/docs/memory_usage.md new file mode 100644 index 0000000..71a8fba --- /dev/null +++ b/docs/memory_usage.md @@ -0,0 +1,94 @@ +# Memory usage + +## Device memory size + +Judging by `.ld` files in [the Ledger Rust SDK](https://github.com/LedgerHQ/ledger-device-rust-sdk/tree/cad196841dbd72c037cfa01bec81a4a3ae57a04e/ledger_secure_sdk_sys/devices), +the amount of SRAM each model has is: +| Device | SRAM | +| ----------------- | ---- | +| apex_p, nanosplus | 40KB | +| flex, stax | 36KB | +| nanox | 28KB | + +The first part of the RAM will be occupied by the app's globals (one of which will be the heap used by the Rust code) and the rest is stack. + +The `HEAP_SIZE` variable in `.cargo/config.toml` specifies the size of the Rust heap (which is just [a static array under the hood](https://github.com/LedgerHQ/ledger-device-rust-sdk/blob/cad196841dbd72c037cfa01bec81a4a3ae57a04e/ledger_secure_sdk_sys/src/lib.rs#L64)). + +I.e. the bigger `HEAP_SIZE` is, the less is the stack. And with the `HEAP_SIZE` of 16KB, we'll have less than 12KB of stack at nanox. + +## Reducing app stack usage + +- Function's parameters and the return value consume stack space (unless the object is small enough to be put into a register). +- Moving an object around inside the function body may increase stack consumption as well. + +So, +- Box large types if you need to pass/return them by value. +- Avoid unboxing boxed large objects when passing them by value. E.g. even if a function only needs `LargeObj`, + pass `Box` to it anyway (which would be discouraged by the "normal" best practices), because passing it + unboxed would increase the stack usage.\ + This includes the case when a member function consumes `self` - declare it as `self: Box` instead. +- `sizeof` of 200 bytes is probably large enough. E.g. in the past boxing certain objects of roughly this size + decreased stack usage by roughly 1.3KB (which is more than 10% of all stack space available on nanox). + +### Determining the current stack usage of the app + +Build the app with `emit-stack-sizes`: +``` +RUSTFLAGS="-Z emit-stack-sizes" cargo ledger build nanox +``` +After that you can use `llvm-readobj` to obtain sizes of stack frames of each function: +``` +llvm-readobj --stack-sizes --demangle target/nanox/release/mintlayer-app +``` + +You can also force `llvm-readobj` to emit json and use `jq` to sort the output by the stack size. E.g. the following +will print 20 functions with the biggest stack frame size: +``` +llvm-readobj --stack-sizes --demangle --elf-output-style=JSON target/nanox/release/mintlayer-app | jq -r '.[].StackSizes | sort_by(.Entry.Size) | reverse | .[:20][] | .Entry | "\(.Size)\t\(.Functions | join(", "))"' +``` + +### Determining the actual available stack + +At least in the current version of the SDK, the linker script emits symbols that +can be used to determine the actual stack size, e.g. via `llvm-readelf`: +``` +llvm-readelf -s target/nanox/release/mintlayer-app | rg '_stack|_estack' +``` +Example output: +``` +1581: da7a425c 0 NOTYPE GLOBAL DEFAULT 6 app_stack_canary +1624: da7a7000 0 NOTYPE GLOBAL DEFAULT 6 _estack +1697: da7a4260 0 NOTYPE GLOBAL DEFAULT 6 _stack +``` +Here `_estack` is the end of the stack area, `_stack` is the beginning of it and `app_stack_canary` is a 4-byte marker +placed just below `_stack` and used to detect stack overflows. The difference between `_estack` and `_stack` will be +the stack size, in this case it's da7a7000-da7a4260=2DA0 (11680 in decimal). + +### Other notes + +This code: +``` +fn foo(x: &X) { + match x { + X::A => { /*do stuff*/ }, + X::B => { /*do other stuff*/ }, + } +} +``` +may use more stack than: +``` +fn foo(x: &X) { + match x { + X::A => stuff(), + X::B => other_stuff(), + } +} + +#[inline(never)] fn stuff() { /*do stuff*/ } +#[inline(never)] fn other_stuff() { /*do other stuff*/ } +``` +I.e. it seems that LLVM cannot always reuse stack slots between different branches of the `match`, and with bigger enums +and bigger stack usage in each branch the overhead becomes bigger as well. So, splitting a large `match` into separate +non-inlinable functions may be a way of reducing the app's stack usage, but this should probably be the last resort, +because if all large objects are boxed, the stack usage in each branch should be relatively small, which will make +the overhead relatively small as well. diff --git a/glyphs/home_nano_nbgl.png b/glyphs/home_nano_nbgl.png new file mode 100644 index 0000000..4fa2028 Binary files /dev/null and b/glyphs/home_nano_nbgl.png differ diff --git a/glyphs/mintlayer_48x48.png b/glyphs/mintlayer_48x48.png new file mode 100644 index 0000000..991e98d Binary files /dev/null and b/glyphs/mintlayer_48x48.png differ diff --git a/glyphs/mintlayer_64x64.gif b/glyphs/mintlayer_64x64.gif new file mode 100644 index 0000000..d5bdcef Binary files /dev/null and b/glyphs/mintlayer_64x64.gif differ diff --git a/icons/mask_14x14.gif b/icons/mask_14x14.gif new file mode 100644 index 0000000..1568a9f Binary files /dev/null and b/icons/mask_14x14.gif differ diff --git a/icons/mintlayer_14x14.gif b/icons/mintlayer_14x14.gif new file mode 100644 index 0000000..df802c2 Binary files /dev/null and b/icons/mintlayer_14x14.gif differ diff --git a/icons/mintlayer_32x32.gif b/icons/mintlayer_32x32.gif new file mode 100644 index 0000000..c1dbbf1 Binary files /dev/null and b/icons/mintlayer_32x32.gif differ diff --git a/icons/mintlayer_32x32.png b/icons/mintlayer_32x32.png new file mode 100644 index 0000000..790b9cd Binary files /dev/null and b/icons/mintlayer_32x32.png differ diff --git a/icons/mintlayer_40x40.gif b/icons/mintlayer_40x40.gif new file mode 100644 index 0000000..c2532c5 Binary files /dev/null and b/icons/mintlayer_40x40.gif differ diff --git a/ledger_app.toml b/ledger_app.toml new file mode 100644 index 0000000..853c6c5 --- /dev/null +++ b/ledger_app.toml @@ -0,0 +1,7 @@ +[app] +build_directory = "./" +sdk = "Rust" +devices = ["nanox", "nanos+", "stax", "flex", "apex_p"] + +[tests] +pytest_directory = "./tests/" diff --git a/run_extra_checks.sh b/run_extra_checks.sh new file mode 100755 index 0000000..2e4eeea --- /dev/null +++ b/run_extra_checks.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +set -e +set -o nounset + +# Run some extra checks (for now its mostly clippy). + +# Notes about clippy: +# 1. Ledger's guideline enforcer also runs it. But at the moment of writing this it doesn't check +# tests, see https://github.com/LedgerHQ/ledger-app-workflows/blob/master/scripts/check_all.sh. +# Besides, we want to enable some additional checks, similar to what we do in Mintlayer Core, +# so we do a separate clippy run here. +# 2. The guideline enforcer runs it for all existing device models, but in this additional run this +# is redundant, so we use one arbitrarily chosen model. +# 3. Unlike in Mintlayer Core, we can't disable certain annoying and mostly useless checks (such as +# let-and-return), because the guideline enforcer will run them anyway. + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) + +cd "$SCRIPT_DIR" + +echo "Running cargo fmt" +cargo fmt --check -- --config newline_style=Unix + +CLIPPY_TARGET_ARG=--target=apex_p + +echo "Running clippy (any code)" +cargo clippy "$CLIPPY_TARGET_ARG" --all-features --workspace --bins --lib --tests -- \ + -D warnings \ + -D clippy::implicit_saturating_sub \ + -D clippy::implicit_clone \ + -D clippy::map_unwrap_or \ + -D clippy::unnested_or_patterns \ + -D clippy::mut_mut \ + -D clippy::todo + +echo "Running clippy (production code)" +# TODO: consider also enabling `unwrap_used` and `items_after_statements`. +cargo clippy "$CLIPPY_TARGET_ARG" --all-features --workspace --bins --lib -- \ + -A clippy::all \ + -D clippy::float_arithmetic \ + -D clippy::dbg_macro \ + -D clippy::fallible_impl_from \ + -D clippy::string_slice + +echo "All checks passed" diff --git a/run_unit_tests.sh b/run_unit_tests.sh new file mode 100755 index 0000000..5f3d45c --- /dev/null +++ b/run_unit_tests.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e +set -o nounset + +# Run unit tests; the first argument must be the device model: nanox, nanosp, stax, flex or apex_p. + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) + +cd "$SCRIPT_DIR" + +MODEL=$1 + +if [[ "$MODEL" == "nanosp" ]]; then + TARGET="nanosplus" +else + TARGET="$MODEL" +fi + +echo "*** Running unit tests on $MODEL ***" + +PACKAGES=(mintlayer-app-core) + +for package in "${PACKAGES[@]}"; do + echo "*** Building unit tests for $package ***" + + output=$(cargo test -p "$package" --release --no-run --message-format=json --target="$TARGET") + jq_selector='select(.reason == "compiler-artifact") | select(.profile.test == true) | select(.executable != null) | .executable' + test_exe_path=$(jq -r "$jq_selector" <<< "$output") + + echo "*** Running unit tests for $package ***" + speculos --display headless --model "$MODEL" "$test_exe_path" +done diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..ffbbd17 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly-2025-12-05" + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..1b527f4 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,29 @@ +/***************************************************************************** + * Mintlayer Ledger App. + * (c) 2023 Ledger SAS. + * (c) 2025 RBB S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#![no_std] +#![no_main] + +use mintlayer_app_core::mintlayer_main; + +ledger_device_sdk::set_panic!(ledger_device_sdk::exiting_panic); + +#[no_mangle] +extern "C" fn sample_main() { + mintlayer_main(); +} diff --git a/tests/application_client/__init__.py b/tests/application_client/__init__.py new file mode 100644 index 0000000..dff703e --- /dev/null +++ b/tests/application_client/__init__.py @@ -0,0 +1,761 @@ +# Copyright (c) 2022 RBB S.r.l +# opensource@mintlayer.org +# SPDX-License-Identifier: MIT +# Licensed under the MIT License; +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://github.com/mintlayer/mintlayer-core/blob/master/LICENSE +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import scalecodec # type: ignore + +MAINNET = 0 +TESTNET = 1 +REGTEST = 2 +SIGNET = 3 + + +def init_mintlayer_types(): + custom_types = { + "types": { + "Bip32Path": "Vec", + "Amount": "Compact", + "H256": "[u8; 32]", + "BlockHeight": "Compact", + "OutputValue": { + "type": "enum", + "type_mapping": [ + ["Coin", "Amount"], + ["TokenV0", ""], # deprecated + ["TokenV1", "(TokenId, Amount)"], + ], + }, + "InputAddressPath": { + "type": "struct", + "type_mapping": [ + ["path", "Vec"], + ["multisig_idx", "Option"], + ], + }, + "InputMeta": { + "type": "struct", + "type_mapping": [ + ["addresses", "Vec"], + ], + }, + "Destination": { + "type": "enum", + "type_mapping": [ + ["AnyoneCanSpend", "()"], + ["Address", "(PublicKeyHash)"], + ["PublicKey", "PublicKey"], + ["ScriptHash", "ScriptId"], + ["ClassicMultiSig", "(PublicKeyHash)"], + ], + }, + "PublicKeyHash": "[u8; 20]", + "PublicKey": { + "type": "struct", + "type_mapping": [ + ["key", "PublicKeyHolder"], + ], + }, + "PublicKeyHolder": { + "type": "enum", + "type_mapping": [ + ["Secp256k1Schnorr", "(Secp256k1PublicKey)"], + ], + }, + "Secp256k1PublicKey": { + "type": "struct", + "type_mapping": [ + ["pubkey_data", "[u8; 33]"], + ], + }, + "IsTokenFreezable": { + "type": "enum", + "type_mapping": [ + ["No", "()"], + ["Yes", "()"], + ], + }, + "TokenTotalSupply": { + "type": "enum", + "type_mapping": [ + ["Fixed", "Amount"], + ["Lockable", "()"], + ["Unlimited", "()"], + ], + }, + "TokenIssuanceV1": { + "type": "struct", + "type_mapping": [ + ["token_ticker", "Vec"], + ["number_of_decimals", "u8"], + ["metadata_uri", "Vec"], + ["total_supply", "TokenTotalSupply"], + ["authority", "Destination"], + ["is_freezable", "IsTokenFreezable"], + ], + }, + "TokenIssuance": { + "type": "enum", + # The Rust enum has an explicit codec index of 1 for the V1 variant. + # A placeholder is added for index 0 to ensure correct encoding. + "type_mapping": [ + ["_Unused", "()"], + ["V1", "TokenIssuanceV1"], + ], + }, + "TokenCreator": { + "type": "struct", + "type_mapping": [ + ["public_key", "PublicKey"], + ], + }, + "Metadata": { + "type": "struct", + "type_mapping": [ + ["creator", "Option"], + ["name", "Vec"], + ["description", "Vec"], + ["ticker", "Vec"], + ["icon_uri", "Vec"], + ["additional_metadata_uri", "Vec"], + ["media_uri", "Vec"], + ["media_hash", "Vec"], + ], + }, + "NftIssuanceV0": { + "type": "struct", + "type_mapping": [ + ["metadata", "Metadata"], + ], + }, + "NftIssuance": { + "type": "enum", + "type_mapping": [ + ["V0", "NftIssuanceV0"], + ], + }, + "TxOutput": { + "type": "enum", + "type_mapping": [ + ["Transfer", "(OutputValue, Destination)"], + ["LockThenTransfer", "(OutputValue, Destination, OutputTimeLock)"], + ["Burn", "(OutputValue)"], + ["CreateStakePool", "(PoolId, StakePoolData)"], + ["ProduceBlockFromStake", "(Destination, PoolId)"], + ["CreateDelegationId", "(Destination, PoolId)"], + ["DelegateStaking", "(Amount, DelegationId)"], + ["IssueFungibleToken", "TokenIssuance"], + ["IssueNft", "(TokenId, NftIssuance, Destination)"], + ["DataDeposit", "Vec"], + ["Htlc", "(OutputValue, HashedTimelockContract)"], + ], + }, + "HashedTimelockContract": { + "type": "struct", + "type_mapping": [ + ["secret_hash", "[u8; 20]"], + ["spend_key", "Destination"], + ["refund_timelock", "OutputTimeLock"], + ["refund_key", "Destination"], + ], + }, + "OutputTimeLock": { + "type": "enum", + "type_mapping": [ + ["UntilHeight", "(BlockHeight)"], + ["UntilTime", "(BlockTimestamp)"], + ["ForBlockCount", "Compact"], + ["ForSeconds", "Compat"], + ], + }, + "PoolId": "H256", + "DelegationId": "H256", + "TokenId": "H256", + "OrderId": "H256", + "StakePoolData": { + "type": "struct", + "type_mapping": [ + ["value", "Amount"], + ["staker", "Destination"], + ["vrf_public_key", "VRFPublicKey"], + ["decommission_key", "Destination"], + ["margin_ratio_per_thousand", "u16"], + ["cost_per_block", "Amount"], + ], + }, + "VRFPublicKey": { + "type": "struct", + "type_mapping": [ + ["key", "VRFPublicKeyHolder"], + ], + }, + "VRFPublicKeyHolder": { + "type": "enum", + "type_mapping": [ + ["Schnorrkel", "(SchnorrkelPublicKey)"], + ], + }, + "SchnorrkelPublicKey": { + "type": "struct", + "type_mapping": [ + ["key", "[u8; 32]"], + ], + }, + "OutPointSourceId": { + "type": "enum", + "type_mapping": [ + ["Transaction", "H256"], + ["BlockReward", "H256"], + ], + }, + "OutPoint": { + "type": "struct", + "type_mapping": [ + ["id", "OutPointSourceId"], + ["index", "u32"], + ], + }, + "AccountNonce": "Compact", + "IsTokenUnfreezable": { + "type": "enum", + "type_mapping": [ + ["No", "()"], + ["Yes", "()"], + ], + }, + "AccountCommand": { + "type": "enum", + "type_mapping": [ + ["MintTokens", "(TokenId, Amount)"], + ["UnmintTokens", "TokenId"], + ["LockTokenSupply", "TokenId"], + ["FreezeToken", "(TokenId, IsTokenUnfreezable)"], + ["UnfreezeToken", "TokenId"], + ["ChangeTokenAuthority", "(TokenId, Destination)"], + ["ConcludeOrder", "OrderId"], + ["FillOrder", "(OrderId, Amount, Destination)"], + ["ChangeTokenMetadataUri", "(TokenId, Vec)"], + ], + }, + "OrderAccountCommand": { + "type": "enum", + "type_mapping": [ + ["FillOrder", "(OrderId, Amount)"], + ["FreezeOrder", "OrderId"], + ["ConcludeOrder", "OrderId"], + ], + }, + "TxInput": { + "type": "enum", + "type_mapping": [ + ["Utxo", "OutPoint"], + ["Account", "(AccountOutPoint)"], + ["AccountCommand", "(AccountNonce, AccountCommand)"], + ["OrderAccountCommand", "OrderAccountCommand"], + ], + }, + "TxInputWithAdditionalInfo": { + "type": "enum", + "type_mapping": [ + ["Utxo", "(OutPoint, AdditionalUtxoInfo)"], + ["Account", "(AccountOutPoint)"], + ["AccountCommand", "(AccountNonce, AccountCommand)"], + ["OrderAccountCommand", "(OrderAccountCommand, AdditionalOrderInfo)"], + ], + }, + "AccountOutPoint": { + "type": "struct", + "type_mapping": [ + ["nonce", "Compact"], + ["account", "AccountSpending"], + ], + }, + "AccountSpending": { + "type": "enum", + "type_mapping": [ + ["Delegation", "(H256, Amount)"], + ], + }, + "TransactionV1": { + "type": "struct", + "type_mapping": [ + ["version", "u8"], # has to be 1 + ["flags", "Compact"], + ["inputs", "Vec"], + ["outputs", "Vec"], + ], + }, + "InputWitness": { + "type": "enum", + "type_mapping": [ + ["NoSignature", "Option>"], + ["Standard", "StandardInputSignature"], + ], + }, + "TokenAdditionalInfo": { + "type": "struct", + "type_mapping": [ + ["num_decimals", "u8"], + ["ticker", "Vec"], + ], + }, + "PoolAdditionalInfo": { + "type": "struct", + "type_mapping": [ + ["staker_balance", "Amount"], + ], + }, + "OrderAdditionalInfo": { + "type": "struct", + "type_mapping": [ + ["initially_asked", "OutputValue"], + ["initially_given", "OutputValue"], + ["ask_balance", "Amount"], + ["give_balance", "Amount"], + ], + }, + "InfoId": { + "type": "enum", + "type_mapping": [ + ["TokenId", "H256"], + ["PoolId", "H256"], + ["OrderId", "H256"], + ], + }, + "SighashInputCommitment": { + "type": "enum", + "type_mapping": [ + ["None", "()"], + ["Utxo", "TxOutput"], + ["ProduceBlockFromStakeUtxo", "(TxOutput, Amount)"], + ["FillOrderAccountCommand", "(OutputValue, OutputValue)"], + [ + "ConcludeOrderAccountCommand", + "(OutputValue, OutputValue, Amount, Amount)", + ], + ], + }, + "TxAdditionalInfo": { + "type": "struct", + "type_mapping": [ + ["token_info", "BTreeMap"], + ["pool_info", "BTreeMap"], + ["order_info", "BTreeMap"], + ], + }, + "StandardInputSignature": { + "type": "struct", + "type_mapping": [ + ["sighash_type", "u8"], + ["raw_signature", "Vec"], + ], + }, + "SignedTransaction": { + "type": "struct", + "type_mapping": [ + ["transaction", "TransactionV1"], + ["signatures", "Vec"], + ], + }, + "PartiallySignedTransaction": { + "type": "struct", + "type_mapping": [ + ["tx", "TransactionV1"], + ["witnesses", "Vec>"], + ["input_utxos", "Vec>"], + ["destinations", "Vec>"], + ["htlc_secrets", "Vec>"], + ["additional_infos", "TxAdditionalInfo"], + ], + }, + "SignedTransactionIntent": { + "type": "struct", + "type_mapping": [ + ["signed_message", "String"], + ["signatures", "Vec>"], + ], + }, + "AuthorizedPublicKeyHashSpend": { + "type": "struct", + "type_mapping": [ + ["public_key", "PublicKey"], + ["signature", "Signature"], + ], + }, + "TxMetadataVersionReq": { + "type": "enum", + "type_mapping": [ + ["V1", "TxMetadataV1Req"], + ], + }, + "TxMetadataV1Req": { + "type": "struct", + "type_mapping": [ + ["num_inputs", "u32"], + ["num_outputs", "u32"], + ], + }, + "TxMetadataReq": { + "type": "struct", + "type_mapping": [ + ["coin", "u8"], + ["version", "TxMetadataVersionReq"], + ], + }, + "TxInputReq": { + "type": "struct", + "type_mapping": [ + ["addresses", "Vec"], + ["inp", "TxInputWithAdditionalInfo"], + ], + }, + "AdditionalUtxoInfo": { + "type": "enum", + "type_mapping": [ + ["Utxo", "TxOutput"], + [ + "PoolInfo", + "(TxOutput, Amount)", + ], + ], + }, + "AdditionalOrderInfo": { + "type": "struct", + "type_mapping": [ + ["initially_asked", "OutputValue"], + ["initially_given", "OutputValue"], + ["ask_balance", "Amount"], + ["give_balance", "Amount"], + ], + }, + "TxOutputReq": { + "type": "struct", + "type_mapping": [ + ["out", "TxOutput"], + ], + }, + "SignTxReq": { + "type": "enum", + "type_mapping": [ + ["Input", "TxInputReq"], + ["InputCommitment", "SighashInputCommitment"], + ["Output", "TxOutputReq"], + ["NextSignature", "()"], + ], + }, + "SignatureResponse": "[u8; 64]", + "MsgSignature": { + "type": "struct", + "type_mapping": [ + ["signature", "SignatureResponse"], + ], + }, + "TxInputSignatureResponse": { + "type": "struct", + "type_mapping": [ + ["signature", "SignatureResponse"], + ["input_idx", "u32"], + ["multisig_idx", "Option"], + ["has_next", "bool"], + ], + }, + "PublicKeyResponse": "[u8; 65]", + "ChainCodeResponse": "[u8; 32]", + "GetPublicKeyResponse": { + "type": "struct", + "type_mapping": [ + ["public_key", "PublicKeyResponse"], + ["chain_code", "ChainCodeResponse"], + ], + }, + "MsgSignatureResponse": { + "type": "struct", + "type_mapping": [ + ["signature", "SignatureResponse"], + ], + }, + "Response": { + "type": "enum", + "type_mapping": [ + ["ExpectingNextChunk", "()"], + ["PublicKey", "GetPublicKeyResponse"], + ["TxSetup", "()"], + ["TxNext", "()"], + ["TxSignature", "TxInputSignatureResponse"], + ["MessageSetup", "()"], + ["MessageSignature", "MsgSignatureResponse"], + ["Pong", "()"], + ], + }, + "SemVer": { + "type": "struct", + "type_mapping": [ + ["major", "u8"], + ["minor", "u8"], + ["patch", "u16"], + ], + }, + "PeerAddressIp4": { + "type": "struct", + "type_mapping": [ + ["ip", "[u8; 4]"], + ["port", "u16"], + ], + }, + "PeerAddressIp6": { + "type": "struct", + "type_mapping": [ + ["ip", "[u8; 16]"], + ["port", "u16"], + ], + }, + "PeerAddress": { + "type": "enum", + "type_mapping": [ + ["Ip4", "PeerAddressIp4"], + ["Ip6", "PeerAddressIp6"], + ], + }, + "HandshakeHello": { + "type": "struct", + "type_mapping": [ + ["protocol", "u32"], + ["network", "[u8; 4]"], + ["services", "u64"], + ["user_agent", "String"], + ["version", "SemVer"], + ["receiver_address", "Option"], + ["current_time", "Compact"], + ["handshake_nonce", "u64"], + ], + }, + "HandshakeHelloAck": { + "type": "struct", + "type_mapping": [ + ["protocol", "u32"], + ["network", "[u8; 4]"], + ["services", "u64"], + ["user_agent", "String"], + ["version", "SemVer"], + ["receiver_address", "Option"], + ["current_time", "Compact"], + ], + }, + "HandshakeMessage": { + "type": "enum", + "type_mapping": [ + ["Hello", "HandshakeHello"], + ["HelloAck", "HandshakeHelloAck"], + ], + }, + "PingMessage": { + "type": "struct", + "type_mapping": [ + ["nonce", "u64"], + ], + }, + "BlockHeader": { + "type": "struct", + "type_mapping": [ + ["version", "u8"], + ["prev_block_id", "H256"], + ["tx_merkle_root", "H256"], + ["witness_merkle_root", "H256"], + ["timestamp", "Compact"], + ["consensus_data", "ConsensusData"], + ], + }, + "SignedBlockHeader": { + "type": "struct", + "type_mapping": [ + ["header", "BlockHeader"], + ["signature", "BlockHeaderSignature"], + ], + }, + "BlockHeaderSignature": { + "type": "enum", + "type_mapping": [ + ["None", "()"], + ["HeaderSignature", "(BlockHeaderSignatureData)"], + ], + }, + "BlockHeaderSignatureData": { + "type": "struct", + "type_mapping": [ + ["signature", "(Signature)"], + ], + }, + "Signature": { + "type": "enum", + "type_mapping": [ + ["Secp256k1Schnorr", "[u8; 64]"], + ], + }, + "ConsensusData": { + "type": "enum", + "type_mapping": [ + ["None", "()"], + ["PoW", "PoWData"], + ["PoS", "PoSData"], + ], + }, + "PoWData": { + "type": "struct", + "type_mapping": [ + ["bits", "u32"], + ["nonce", "u128"], + ], + }, + "PoSData": { + "type": "struct", + "type_mapping": [ + ["kernel_inputs", "Vec"], + ["kernel_witness", "Vec"], + ["stake_pool_id", "PoolId"], + ["vrf_data", "VRFReturn"], + ["compact_target", "u32"], + ], + }, + "VRFReturn": { + "type": "enum", + "type_mapping": [ + ["Schnorrkel", "(SchnorrkelVRFReturn)"], + ], + }, + "SchnorrkelVRFReturn": { + "type": "struct", + "type_mapping": [ + ["preout", "[u8; 32]"], + ["proof", "[u8; 64]"], + ], + }, + "BlockIdAtHeight": "H256", + "BlockBody": { + "type": "struct", + "type_mapping": [ + ["reward", "BlockReward"], + ["transactions", "Vec"], + ], + }, + "BlockReward": { + "type": "struct", + "type_mapping": [ + ["reward_outputs", "Vec"], + ], + }, + "Block": { + "type": "enum", + "type_mapping": [ + ["V1", "(BlockV1)"], + ], + }, + "BlockV1": { + "type": "struct", + "type_mapping": [ + ["header", "SignedBlockHeader"], + ["body", "BlockBody"], + ], + }, + "Id": "[u8; 32]", + "HeaderListRequest": "Vec", + "HeaderList": "Vec", + "TransactionResponse": { + "type": "enum", + "type_mapping": [ + ["not_found", "Id"], + ["found", "SignedTransaction"], + ], + }, + "Message": { + "type": "enum", + "type_mapping": [ + ["handshake", "HandshakeMessage"], + ["ping_request", "PingMessage"], + ["ping_response", "PingMessage"], + ["new_transaction", "Id"], + ["header_list_request", "HeaderListRequest"], + ["header_list", "HeaderList"], + ["block_list_request", "Vec"], + ["block_response", "()"], + ["announce_addr_request", "PeerAddress"], + ["addr_list_request", "()"], + ["addr_list_response", "Vec"], + ["transaction_request", "Id"], + ["transaction_response", "TransactionResponse"], + ], + }, + "GenerateBlockInputData": { + "type": "enum", + "type_mapping": [ + ["None", "()"], + ["PoW", "PoWGenerateBlockInputData"], + ["PoS", "PoSGenerateBlockInputData"], + ], + }, + "PoSGenerateBlockInputData": { + "type": "struct", + "type_mapping": [ + ["stake_private_key", "PrivateKey"], + ["vrf_private_key", "VRFPrivateKey"], + ["pool_id", "PoolId"], + ["kernel_inputs", "Vec"], + ["kernel_input_utxo", "Vec"], + ], + }, + "Privatekey": { + "type": "struct", + "type_mapping": [ + ["key", "PrivateKeyHolder"], + ], + }, + "PrivateKeyHolder": { + "type": "enum", + "type_mapping": [ + ["Secp256k1Schnorr", "(Secp256k1PrivateKey)"], + ], + }, + "Secp256k1PrivateKey": { + "type": "struct", + "type_mapping": [ + ["data", "[u8; 32]"], + ], + }, + "VRFPrivateKey": { + "type": "struct", + "type_mapping": [ + ["key", "VRFPrivateKeyHolder"], + ], + }, + "VRFPrivateKeyHolder": { + "type": "enum", + "type_mapping": [ + ["Schnorrkel", "(SchnorrkelPrivateKey)"], + ], + }, + "SchnorrkelPrivateKey": { + "type": "struct", + "type_mapping": [["key", "[u8; 64]"]], + }, + "PoWGenerateBlockInputData": { + "type": "struct", + "type_mapping": [ + ["reward_destination", "Destination"], + ], + }, + } + } + + scalecodec.base.RuntimeConfiguration().update_type_registry(custom_types) + + +init_mintlayer_types() diff --git a/tests/application_client/mintlayer_command_sender.py b/tests/application_client/mintlayer_command_sender.py new file mode 100644 index 0000000..939d5e4 --- /dev/null +++ b/tests/application_client/mintlayer_command_sender.py @@ -0,0 +1,416 @@ +from contextlib import contextmanager +from dataclasses import dataclass +from enum import IntEnum +from typing import Any, Generator, List, Optional + +import scalecodec # type: ignore +from ragger.backend.interface import RAPDU, BackendInterface +from ragger.navigator import NavInsID +from ragger.navigator.navigation_scenario import NavigationScenarioData, UseCase + +from .mintlayer_transaction import Transaction + +tx_metadata_obj = scalecodec.base.RuntimeConfiguration().create_scale_object( + "TxMetadataReq" +) +sign_tx_req_obj = scalecodec.base.RuntimeConfiguration().create_scale_object( + "SignTxReq" +) + +MAX_APDU_LEN: int = 255 +TX_RESPONSE_SIZE: int = 71 + +CLA: int = 0xE1 + +@dataclass +class ReviewTransaction: + transaction: Transaction + has_command_input: bool + review_custom_screen_text: str + +@dataclass +class SignTxStep: + kind: str + index: int | None = None + +class GetAppAndVersionP1(IntEnum): + # Parameter 1 for first APDU number. + P1_START = 0x00 + P1_NEXT = 0x01 + +class SignTxP1(IntEnum): + # Parameter 1 for first APDU number. + P1_START = 0x00 + P1_NEXT = 0x01 + +class SignMessageP1(IntEnum): + # Parameter 1 for first APDU number. + P1_START = 0x00 + P1_NEXT = 0x01 + +class GetPublicKeyP1(IntEnum): + P1_START = 0x00 + # Parameter 1 for screen confirmation for GET_PUBLIC_KEY. + P1_CONFIRM = 0x01 + + +class P2(IntEnum): + # Parameter 2 for last APDU to receive. + P2_LAST = 0x00 + # Parameter 2 for more APDU to receive. + P2_MORE = 0x80 + + +class InsType(IntEnum): + GET_PUBLIC_KEY = 0x00 + SIGN_TX = 0x01 + SIGN_MESSAGE = 0x02 + + +class Errors(IntEnum): + SW_DENY = 0x6985 + SW_CLA_NOT_SUPPORTED = 0x6E00 + SW_INS_NOT_SUPPORTED = 0x6E01 + SW_WRONG_P1P2 = 0x6E02 + SW_WRONG_APDU_LENGTH = 0x6E03 + + SW_WRONG_RESPONSE_LENGTH = 0xB000 + SW_DISPLAY_BIP32_PATH_FAIL = 0xB001 + SW_WRONG_TX_LENGTH = 0xB002 + SW_WRONG_CONTEXT = 0xB008 + SW_DESERIALIZE_FAIL = 0xB009 + SW_MAX_BUFFER_LEN_EXCEEDED = 0xB012 + + +def split_message(message: bytes, max_size: int) -> List[bytes]: + return [message[x : x + max_size] for x in range(0, len(message), max_size)] + + +class MintlayerCommandSender: + def __init__(self, backend: BackendInterface) -> None: + self.backend = backend + + def get_app_and_version(self) -> RAPDU: + return self.backend.exchange( + cla=0xB0, # specific CLA for BOLOS + ins=0x01, # specific INS for get_app_and_version + p1=GetAppAndVersionP1.P1_START, + p2=P2.P2_LAST, + data=b"", + ) + + def get_public_key(self, coin: int, path: str) -> RAPDU: + data = coin.to_bytes(1, "little") + pack_derivation_path(path) + + return self.backend.exchange( + cla=CLA, + ins=InsType.GET_PUBLIC_KEY, + p1=GetPublicKeyP1.P1_START, + p2=P2.P2_LAST, + data=data, + ) + + @contextmanager + def get_public_key_with_confirmation( + self, coin: int, path: str + ) -> Generator[None, None, None]: + data = coin.to_bytes(1, "little") + pack_derivation_path(path) + + with self.backend.exchange_async( + cla=CLA, + ins=InsType.GET_PUBLIC_KEY, + p1=GetPublicKeyP1.P1_CONFIRM, + p2=P2.P2_LAST, + data=data, + ) as response: + yield response + + @contextmanager + def sign_message( + self, coin: int, addr_type: int, path: str, message: bytes + ) -> Generator[None, None, None]: + data = ( + coin.to_bytes(1, "little") + + addr_type.to_bytes(1, "little") + + pack_derivation_path(path) + ) + + self.backend.exchange( + cla=CLA, ins=InsType.SIGN_MESSAGE, p1=SignMessageP1.P1_START, p2=P2.P2_LAST, data=data + ) + chunks = split_message(message, MAX_APDU_LEN) + + for chunk in chunks[:-1]: + self.backend.exchange( + cla=CLA, + ins=InsType.SIGN_MESSAGE, + p1=SignMessageP1.P1_NEXT, + p2=P2.P2_MORE, + data=chunk + ) + + with self.backend.exchange_async( + cla=CLA, + ins=InsType.SIGN_MESSAGE, + p1=SignMessageP1.P1_NEXT, + p2=P2.P2_LAST, + data=chunks[-1] + ) as response: + yield response + + def sign_tx(self, transaction: Transaction) -> Generator[SignTxStep, None, None]: + # ---- METADATA ---- + metadata = tx_metadata_obj.encode( + { + "coin": transaction.coin, + "version": { + "V1": { + "num_inputs": len(transaction.inputs), + "num_outputs": len(transaction.outputs), + }, + }, + } + ).data + + res = self.backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_START, + p2=P2.P2_LAST, + data=bytes(metadata), + ) + print("metadata ", res) + + # ---- INPUTS ---- + print("sending inputs", len(transaction.inputs)) + + for inp in transaction.inputs: + self._send_chunked_sync(inp) + + # ---- INPUT COMMITMENTS ---- + print("sending input commitments") + + for inp in transaction.input_commitments[:-1]: + self._send_chunked_sync(inp) + + chunks = split_message(transaction.input_commitments[-1], MAX_APDU_LEN) + + # all but last chunk sync + for chunk in chunks[:-1]: + self.backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, + p2=P2.P2_MORE, + data=chunk, + ) + + # last chunk async -> UI review + with self.backend.exchange_async( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, + p2=P2.P2_LAST, + data=chunks[-1], + ): + kind = "start" + yield SignTxStep(kind=kind, index=0) + + + # ---- OUTPUTS ---- + print("streaming outputs") + + for idx, out in enumerate(transaction.outputs): + print(f"sending output {idx}") + + chunks = split_message(out, MAX_APDU_LEN) + + # all but last chunk sync + for chunk in chunks[:-1]: + self.backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, + p2=P2.P2_MORE, + data=chunk, + ) + + # last chunk async -> UI review + with self.backend.exchange_async( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, + p2=P2.P2_LAST, + data=chunks[-1], + ): + kind = "final" if idx == len(transaction.outputs) - 1 else "output" + yield SignTxStep(kind=kind, index=idx) + + def _send_chunked_sync(self, data: bytes): + chunks = split_message(data, MAX_APDU_LEN) + + for chunk in chunks[:-1]: + self.backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, + p2=P2.P2_MORE, + data=chunk, + ) + + self.backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, + p2=P2.P2_LAST, + data=chunks[-1], + ) + + def get_async_response(self) -> Optional[RAPDU]: + return self.backend.last_async_response + + def get_all_signatures(self, tx: Transaction) -> List[bytes | Any]: + if self.backend.last_async_response is None: + raise ValueError("None response") + + next_sig = sign_tx_req_obj.encode({"NextSignature": None}).data + responses = [self.backend.last_async_response.data] + for _ in tx.inputs[1:]: + res = self.backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, + p2=P2.P2_LAST, + data=next_sig, + ) + if res is not None: + responses.append(res.data) + else: + raise ValueError("None response") + return responses + + +def hardened_index(index: int) -> int: + return index | 1 << 31 + + +def pack_derivation_path(derivation_path: str) -> bytes: + path_obj = scalecodec.base.RuntimeConfiguration().create_scale_object("Bip32Path") + + split = derivation_path.split("/") + + if split[0] != "m": + raise ValueError("Error master expected") + + path = [] + for value in split[1:]: + if value == "": + raise ValueError(f'Error missing value in split list "{split}"') + if value.endswith("'"): + path.append(hardened_index(int(value[:-1]))) + else: + path.append(int(value)) + + return path_obj.encode(path).data + + +def sign_tx_review( + client, + device, + navigator, + scenario_navigator, + review_transaction: ReviewTransaction, +): + transaction = review_transaction.transaction + has_command_input = review_transaction.has_command_input + review_custom_screen_text = review_transaction.review_custom_screen_text + + start_idx = 0 + if not device.is_nano: + instruction = NavInsID.SWIPE_CENTER_TO_LEFT + else: + instruction = NavInsID.RIGHT_CLICK + + last_page_pattern=r".*\((\d+)/\1\)$" + + for step in client.sign_tx(transaction): + print("step kind: ", step.kind) + if step.kind == "start": + navigator.navigate_and_compare( + path=scenario_navigator.screenshot_path, + test_case_name=scenario_navigator.test_name, + instructions=[instruction], + screen_change_before_first_instruction=False, + screen_change_after_last_instruction=False, + snap_start_idx=start_idx, + ) + start_idx += 10 + + if has_command_input: + if device.is_nano: + navigator.navigate_until_text_and_compare( + navigate_instruction=instruction, + validation_instructions=[instruction], + text=last_page_pattern, + path=scenario_navigator.screenshot_path, + test_case_name=scenario_navigator.test_name, + screen_change_before_first_instruction=False, + screen_change_after_last_instruction=False, + snap_start_idx=start_idx, + ) + else: + navigator.navigate_and_compare( + path=scenario_navigator.screenshot_path, + test_case_name=scenario_navigator.test_name, + instructions=[instruction] * 2, + screen_change_before_first_instruction=False, + screen_change_after_last_instruction=False, + snap_start_idx=start_idx, + ) + start_idx += 10 + + if step.kind == "output": + if device.is_nano: + navigator.navigate_until_text_and_compare( + navigate_instruction=instruction, + validation_instructions=[instruction], + text=last_page_pattern, + path=scenario_navigator.screenshot_path, + test_case_name=scenario_navigator.test_name, + screen_change_before_first_instruction=False, + screen_change_after_last_instruction=False, + snap_start_idx=start_idx, + ) + else: + navigator.navigate_and_compare( + path=scenario_navigator.screenshot_path, + test_case_name=scenario_navigator.test_name, + instructions=[instruction] * 2, + screen_change_before_first_instruction=False, + screen_change_after_last_instruction=False, + snap_start_idx=start_idx, + ) + start_idx += 10 + + elif step.kind == "final": + scenario = NavigationScenarioData( + scenario_navigator.device, + scenario_navigator.backend, + UseCase.TX_REVIEW, + True) + navigator.navigate_until_text_and_compare( + navigate_instruction=scenario.navigation, + validation_instructions=scenario.validation, + text=review_custom_screen_text, + path=scenario_navigator.screenshot_path, + test_case_name=scenario_navigator.test_name, + screen_change_after_last_instruction=False, + snap_start_idx=start_idx, + ) + + # The device as yielded the result, parse it and ensure that the signature is correct + responses = client.get_all_signatures(transaction) + + assert len(responses) == len(transaction.inputs) + for response in responses: + assert len(response) == TX_RESPONSE_SIZE diff --git a/tests/application_client/mintlayer_response_unpacker.py b/tests/application_client/mintlayer_response_unpacker.py new file mode 100644 index 0000000..edb28d4 --- /dev/null +++ b/tests/application_client/mintlayer_response_unpacker.py @@ -0,0 +1,86 @@ +from struct import unpack +from typing import Tuple + +import scalecodec # type: ignore + + +# remainder, data_len, data +def pop_sized_buf_from_buffer(buffer: bytes, size: int) -> Tuple[bytes, bytes]: + return buffer[size:], buffer[0:size] + + +# remainder, data_len, data +def pop_size_prefixed_buf_from_buf(buffer: bytes) -> Tuple[bytes, int, bytes]: + data_len = buffer[0] + return buffer[1 + data_len :], data_len, buffer[1 : data_len + 1] + + +# Unpack from response: +# response = app_name (var) +def unpack_get_app_name_response(response: bytes) -> str: + return response.decode("ascii") + + +# Unpack from response: +# response = MAJOR (1) +# MINOR (1) +# PATCH (1) +def unpack_get_version_response(response: bytes) -> Tuple[int, int, int]: + assert len(response) == 3 + major, minor, patch = unpack("BBB", response) + return (major, minor, patch) + + +# Unpack from response: +# response = format_id (1) +# app_name_raw_len (1) +# app_name_raw (var) +# version_raw_len (1) +# version_raw (var) +# unused_len (1) +# unused (var) +def unpack_get_app_and_version_response(response: bytes) -> Tuple[str, str]: + response, _ = pop_sized_buf_from_buffer(response, 1) + response, _, app_name_raw = pop_size_prefixed_buf_from_buf(response) + response, _, version_raw = pop_size_prefixed_buf_from_buf(response) + response, _, _ = pop_size_prefixed_buf_from_buf(response) + + assert len(response) == 0 + + return app_name_raw.decode("ascii"), version_raw.decode("ascii") + + +# Unpack from response: +def unpack_get_public_key_response(response: bytes) -> Tuple[int, bytes, int, bytes]: + response_bytes = scalecodec.base.ScaleBytes(response) + response_obj = scalecodec.base.RuntimeConfiguration().create_scale_object( + "Response", data=response_bytes + ) + msg = response_obj.decode() + + print(msg) + + pub_key = bytes.fromhex(msg["PublicKey"]["public_key"][2:]) + pub_key_len = len(pub_key) + chain_code = bytes.fromhex(msg["PublicKey"]["chain_code"][2:]) + chain_code_len = len(chain_code) + + print(pub_key_len, pub_key) + print(chain_code_len, chain_code) + + assert pub_key_len == 65 + assert chain_code_len == 32 + return pub_key_len, pub_key, chain_code_len, chain_code + + +# Unpack from response: +def unpack_sign_message_response(response: bytes) -> bytes: + response_bytes = scalecodec.base.ScaleBytes(response) + response_obj = scalecodec.base.RuntimeConfiguration().create_scale_object( + "Response", data=response_bytes + ) + resp = response_obj.decode() + assert resp["MessageSignature"] is not None + signature = bytes.fromhex(resp["MessageSignature"]["signature"][2:]) + assert len(signature) == 64 + return signature diff --git a/tests/application_client/mintlayer_transaction.py b/tests/application_client/mintlayer_transaction.py new file mode 100644 index 0000000..acd6ac1 --- /dev/null +++ b/tests/application_client/mintlayer_transaction.py @@ -0,0 +1,14 @@ +from dataclasses import dataclass +from typing import List + + +class TransactionError(Exception): + pass + + +@dataclass +class Transaction: + coin: int + inputs: List[bytes] + input_commitments: List[bytes] + outputs: List[bytes] diff --git a/tests/application_client/mintlayer_utils.py b/tests/application_client/mintlayer_utils.py new file mode 100644 index 0000000..fd96e62 --- /dev/null +++ b/tests/application_client/mintlayer_utils.py @@ -0,0 +1,61 @@ +from io import BytesIO +from typing import Optional, Literal + + +UINT64_MAX: int = 2**64-1 +UINT32_MAX: int = 2**32-1 +UINT16_MAX: int = 2**16-1 + + +def write_varint(n: int) -> bytes: + if n < 0xFC: + return n.to_bytes(1, byteorder="little") + + if n <= UINT16_MAX: + return b"\xFD" + n.to_bytes(2, byteorder="little") + + if n <= UINT32_MAX: + return b"\xFE" + n.to_bytes(4, byteorder="little") + + if n <= UINT64_MAX: + return b"\xFF" + n.to_bytes(8, byteorder="little") + + raise ValueError(f"Can't write to varint: '{n}'!") + + +def read_varint(buf: BytesIO, + prefix: Optional[bytes] = None) -> int: + b: bytes = prefix if prefix else buf.read(1) + + if not b: + raise ValueError(f"Can't read prefix: '{b.hex()}'!") + + n: int = {b"\xfd": 2, b"\xfe": 4, b"\xff": 8}.get(b, 1) # default to 1 + + b = buf.read(n) if n > 1 else b + + if len(b) != n: + raise ValueError("Can't read varint!") + + return int.from_bytes(b, byteorder="little") + + +def read(buf: BytesIO, size: int) -> bytes: + b: bytes = buf.read(size) + + if len(b) < size: + raise ValueError(f"Can't read {size} bytes in buffer!") + + return b + + +def read_uint(buf: BytesIO, + bit_len: int, + byteorder: Literal['big', 'little'] = 'little') -> int: + size: int = bit_len // 8 + b: bytes = buf.read(size) + + if len(b) < size: + raise ValueError(f"Can't read u{bit_len} in buffer!") + + return int.from_bytes(b, byteorder) diff --git a/tests/application_client/py.typed b/tests/application_client/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/tests/boil-freeze.txt b/tests/boil-freeze.txt new file mode 100644 index 0000000..a74fc92 --- /dev/null +++ b/tests/boil-freeze.txt @@ -0,0 +1,60 @@ +aniso8601==9.0.1 +asn1crypto==1.5.1 +attrs==22.2.0 +bip-utils==2.7.0 +cbor2==5.4.6 +certifi==2022.12.7 +cffi==1.15.1 +charset-normalizer==3.0.1 +click==8.1.3 +coincurve==17.0.0 +construct==2.10.68 +crcmod==1.7 +cryptography==39.0.1 +ecdsa==0.16.1 +ed25519-blake2b==1.4 +exceptiongroup==1.1.0 +Flask==2.1.2 +Flask-RESTful==0.3.9 +hidapi==0.13.1 +idna==3.4 +importlib-metadata==6.0.0 +importlib-resources==5.12.0 +iniconfig==2.0.0 +intelhex==2.3.0 +itsdangerous==2.1.2 +Jinja2==3.1.2 +jsonschema==4.17.3 +ledgerwallet==0.2.3 +MarkupSafe==2.1.2 +mnemonic==0.20 +packaging==23.0 +Pillow==9.4.0 +pkg_resources==0.0.0 +pkgutil_resolve_name==1.3.10 +pluggy==1.0.0 +protobuf==3.20.3 +py-sr25519-bindings==0.1.4 +pycparser==2.21 +pycryptodome==3.17 +pyelftools==0.29 +PyNaCl==1.5.0 +PyQt5==5.15.9 +PyQt5-Qt5==5.15.2 +PyQt5-sip==12.11.1 +pyrsistent==0.19.3 +pysha3==1.0.2 +pytesseract==0.3.10 +pytest==7.2.1 +pytz==2022.7.1 +ragger==1.6.0 +requests==2.28.2 +semver==2.13.0 +six==1.16.0 +speculos==0.1.224 +tabulate==0.9.0 +toml==0.10.2 +tomli==2.0.1 +urllib3==1.26.14 +Werkzeug==2.2.3 +zipp==3.15.0 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..0315a04 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,19 @@ +import pytest +from ragger.conftest import configuration +from ragger.navigator import NavInsID + +########################### +### CONFIGURATION START ### +########################### + +# You can configure optional parameters by overriding the value of ragger.configuration.OPTIONAL_CONFIGURATION +# Please refer to ragger/conftest/configuration.py for their descriptions and accepted values + +configuration.OPTIONAL.CUSTOM_SEED = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" + +######################### +### CONFIGURATION END ### +######################### + +# Pull all features from the base ragger conftest using the overridden configuration +pytest_plugins = ("ragger.conftest.base_conftest",) diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..fdc689b --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,6 @@ +pytest +ragger[speculos,ledgerwallet]>=1.21.1 +ecdsa>=0.16.1,<0.17.0 +safe-pysha3>=1.0.0,<2.0.0 +tomli>=2.0.1 +scalecodec>=1.2.11 \ No newline at end of file diff --git a/tests/setup.cfg b/tests/setup.cfg new file mode 100644 index 0000000..7d0d7e3 --- /dev/null +++ b/tests/setup.cfg @@ -0,0 +1,21 @@ +[tool:pytest] +addopts = --strict-markers + +[pylint] +disable = C0114, # missing-module-docstring + C0115, # missing-class-docstring + C0116, # missing-function-docstring + C0103, # invalid-name + R0801, # duplicate-code + R0913 # too-many-arguments +max-line-length=100 +extension-pkg-whitelist=hid + +[pycodestyle] +max-line-length = 100 + +[mypy-hid.*] +ignore_missing_imports = True + +[mypy-pytest.*] +ignore_missing_imports = True diff --git a/tests/snapshots/apex_p/test_app_mainmenu/00000.png b/tests/snapshots/apex_p/test_app_mainmenu/00000.png new file mode 100644 index 0000000..5784e46 Binary files /dev/null and b/tests/snapshots/apex_p/test_app_mainmenu/00000.png differ diff --git a/tests/snapshots/apex_p/test_app_mainmenu/00001.png b/tests/snapshots/apex_p/test_app_mainmenu/00001.png new file mode 100644 index 0000000..fff0d0d Binary files /dev/null and b/tests/snapshots/apex_p/test_app_mainmenu/00001.png differ diff --git a/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00000.png b/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00000.png new file mode 100644 index 0000000..d405490 Binary files /dev/null and b/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00000.png differ diff --git a/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00001.png b/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00001.png new file mode 100644 index 0000000..0285ec5 Binary files /dev/null and b/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00001.png differ diff --git a/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00002.png b/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00002.png new file mode 100644 index 0000000..6ce358d Binary files /dev/null and b/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00002.png differ diff --git a/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00003.png b/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00003.png new file mode 100644 index 0000000..5784e46 Binary files /dev/null and b/tests/snapshots/apex_p/test_get_public_key_confirm_accepted/00003.png differ diff --git a/tests/snapshots/apex_p/test_get_public_key_confirm_refused/00000.png b/tests/snapshots/apex_p/test_get_public_key_confirm_refused/00000.png new file mode 100644 index 0000000..d405490 Binary files /dev/null and b/tests/snapshots/apex_p/test_get_public_key_confirm_refused/00000.png differ diff --git a/tests/snapshots/apex_p/test_get_public_key_confirm_refused/00001.png b/tests/snapshots/apex_p/test_get_public_key_confirm_refused/00001.png new file mode 100644 index 0000000..0285ec5 Binary files /dev/null and b/tests/snapshots/apex_p/test_get_public_key_confirm_refused/00001.png differ diff --git a/tests/snapshots/apex_p/test_get_public_key_confirm_refused/00002.png b/tests/snapshots/apex_p/test_get_public_key_confirm_refused/00002.png new file mode 100644 index 0000000..0f7f5fe Binary files /dev/null and b/tests/snapshots/apex_p/test_get_public_key_confirm_refused/00002.png differ diff --git a/tests/snapshots/apex_p/test_sign_message/00000.png b/tests/snapshots/apex_p/test_sign_message/00000.png new file mode 100644 index 0000000..16b258a Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_message/00001.png b/tests/snapshots/apex_p/test_sign_message/00001.png new file mode 100644 index 0000000..333d923 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message/00001.png differ diff --git a/tests/snapshots/apex_p/test_sign_message/00002.png b/tests/snapshots/apex_p/test_sign_message/00002.png new file mode 100644 index 0000000..fc21acc Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message/00002.png differ diff --git a/tests/snapshots/apex_p/test_sign_message/00003.png b/tests/snapshots/apex_p/test_sign_message/00003.png new file mode 100644 index 0000000..d0ceff0 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message/00003.png differ diff --git a/tests/snapshots/apex_p/test_sign_message/00004.png b/tests/snapshots/apex_p/test_sign_message/00004.png new file mode 100644 index 0000000..5784e46 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message/00004.png differ diff --git a/tests/snapshots/apex_p/test_sign_message_pkh/00000.png b/tests/snapshots/apex_p/test_sign_message_pkh/00000.png new file mode 100644 index 0000000..16b258a Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message_pkh/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_message_pkh/00001.png b/tests/snapshots/apex_p/test_sign_message_pkh/00001.png new file mode 100644 index 0000000..a585a87 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message_pkh/00001.png differ diff --git a/tests/snapshots/apex_p/test_sign_message_pkh/00002.png b/tests/snapshots/apex_p/test_sign_message_pkh/00002.png new file mode 100644 index 0000000..fc21acc Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message_pkh/00002.png differ diff --git a/tests/snapshots/apex_p/test_sign_message_pkh/00003.png b/tests/snapshots/apex_p/test_sign_message_pkh/00003.png new file mode 100644 index 0000000..d0ceff0 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message_pkh/00003.png differ diff --git a/tests/snapshots/apex_p/test_sign_message_pkh/00004.png b/tests/snapshots/apex_p/test_sign_message_pkh/00004.png new file mode 100644 index 0000000..5784e46 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message_pkh/00004.png differ diff --git a/tests/snapshots/apex_p/test_sign_message_refused/00000.png b/tests/snapshots/apex_p/test_sign_message_refused/00000.png new file mode 100644 index 0000000..16b258a Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message_refused/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_message_refused/00001.png b/tests/snapshots/apex_p/test_sign_message_refused/00001.png new file mode 100644 index 0000000..333d923 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message_refused/00001.png differ diff --git a/tests/snapshots/apex_p/test_sign_message_refused/00002.png b/tests/snapshots/apex_p/test_sign_message_refused/00002.png new file mode 100644 index 0000000..fc21acc Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message_refused/00002.png differ diff --git a/tests/snapshots/apex_p/test_sign_message_refused/00003.png b/tests/snapshots/apex_p/test_sign_message_refused/00003.png new file mode 100644 index 0000000..419b616 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message_refused/00003.png differ diff --git a/tests/snapshots/apex_p/test_sign_message_refused/00004.png b/tests/snapshots/apex_p/test_sign_message_refused/00004.png new file mode 100644 index 0000000..f411cb4 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_message_refused/00004.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00000.png b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00010.png b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00010.png new file mode 100644 index 0000000..534147d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00011.png b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00011.png new file mode 100644 index 0000000..534147d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00020.png b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00020.png new file mode 100644 index 0000000..bad1ebd Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00020.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00021.png b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00021.png new file mode 100644 index 0000000..113692d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00021.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00022.png b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00022.png new file mode 100644 index 0000000..3f03cbc Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00022.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00023.png b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00023.png new file mode 100644 index 0000000..e36e7a9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_authority/00023.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00000.png b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00010.png b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00010.png new file mode 100644 index 0000000..8ba60e7 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00011.png b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00011.png new file mode 100644 index 0000000..8ba60e7 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00020.png b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00020.png new file mode 100644 index 0000000..bad1ebd Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00020.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00021.png b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00021.png new file mode 100644 index 0000000..113692d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00021.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00022.png b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00022.png new file mode 100644 index 0000000..61b4e75 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00022.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00023.png b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00023.png new file mode 100644 index 0000000..e36e7a9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_change_token_metadata_uri/00023.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_create_delegation/00000.png b/tests/snapshots/apex_p/test_sign_tx_create_delegation/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_create_delegation/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_create_delegation/00010.png b/tests/snapshots/apex_p/test_sign_tx_create_delegation/00010.png new file mode 100644 index 0000000..a3a5a41 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_create_delegation/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_create_delegation/00011.png b/tests/snapshots/apex_p/test_sign_tx_create_delegation/00011.png new file mode 100644 index 0000000..fd7c3fd Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_create_delegation/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_create_delegation/00012.png b/tests/snapshots/apex_p/test_sign_tx_create_delegation/00012.png new file mode 100644 index 0000000..e9c3e68 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_create_delegation/00012.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_create_delegation/00013.png b/tests/snapshots/apex_p/test_sign_tx_create_delegation/00013.png new file mode 100644 index 0000000..4aba0a2 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_create_delegation/00013.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00000.png b/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00010.png b/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00010.png new file mode 100644 index 0000000..a94a8b0 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00011.png b/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00011.png new file mode 100644 index 0000000..113692d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00012.png b/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00012.png new file mode 100644 index 0000000..8afd400 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00012.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00013.png b/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00013.png new file mode 100644 index 0000000..4aba0a2 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_create_stake_pool/00013.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00000.png b/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00010.png b/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00010.png new file mode 100644 index 0000000..b3ab59b Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00011.png b/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00011.png new file mode 100644 index 0000000..8a3ce9b Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00012.png b/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00012.png new file mode 100644 index 0000000..c5cae15 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00012.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00013.png b/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00013.png new file mode 100644 index 0000000..4aba0a2 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_delegation_staking/00013.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00000.png b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00010.png b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00010.png new file mode 100644 index 0000000..cd93b66 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00011.png b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00011.png new file mode 100644 index 0000000..cd93b66 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00020.png b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00020.png new file mode 100644 index 0000000..bad1ebd Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00020.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00021.png b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00021.png new file mode 100644 index 0000000..113692d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00021.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00022.png b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00022.png new file mode 100644 index 0000000..9b7a3e8 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00022.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00023.png b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00023.png new file mode 100644 index 0000000..e36e7a9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_freeze_tokens/00023.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_htlc/00000.png b/tests/snapshots/apex_p/test_sign_tx_htlc/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_htlc/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_htlc/00010.png b/tests/snapshots/apex_p/test_sign_tx_htlc/00010.png new file mode 100644 index 0000000..c2df644 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_htlc/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_htlc/00011.png b/tests/snapshots/apex_p/test_sign_tx_htlc/00011.png new file mode 100644 index 0000000..c2df644 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_htlc/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_htlc/00020.png b/tests/snapshots/apex_p/test_sign_tx_htlc/00020.png new file mode 100644 index 0000000..c2afd83 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_htlc/00020.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_htlc/00021.png b/tests/snapshots/apex_p/test_sign_tx_htlc/00021.png new file mode 100644 index 0000000..113692d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_htlc/00021.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_htlc/00022.png b/tests/snapshots/apex_p/test_sign_tx_htlc/00022.png new file mode 100644 index 0000000..41f624c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_htlc/00022.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_htlc/00023.png b/tests/snapshots/apex_p/test_sign_tx_htlc/00023.png new file mode 100644 index 0000000..4aba0a2 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_htlc/00023.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00000.png b/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00010.png b/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00010.png new file mode 100644 index 0000000..5b427d9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00011.png b/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00011.png new file mode 100644 index 0000000..fd7c3fd Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00012.png b/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00012.png new file mode 100644 index 0000000..039058c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00012.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00013.png b/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00013.png new file mode 100644 index 0000000..4aba0a2 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_issue_fungible_token/00013.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_issue_nft/00000.png b/tests/snapshots/apex_p/test_sign_tx_issue_nft/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_issue_nft/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_issue_nft/00010.png b/tests/snapshots/apex_p/test_sign_tx_issue_nft/00010.png new file mode 100644 index 0000000..6a272b9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_issue_nft/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_issue_nft/00011.png b/tests/snapshots/apex_p/test_sign_tx_issue_nft/00011.png new file mode 100644 index 0000000..3eda950 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_issue_nft/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_issue_nft/00012.png b/tests/snapshots/apex_p/test_sign_tx_issue_nft/00012.png new file mode 100644 index 0000000..6fa38da Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_issue_nft/00012.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_issue_nft/00013.png b/tests/snapshots/apex_p/test_sign_tx_issue_nft/00013.png new file mode 100644 index 0000000..4aba0a2 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_issue_nft/00013.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00000.png b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00010.png b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00010.png new file mode 100644 index 0000000..49bf43a Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00011.png b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00011.png new file mode 100644 index 0000000..49bf43a Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00020.png b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00020.png new file mode 100644 index 0000000..7f2f290 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00020.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00021.png b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00021.png new file mode 100644 index 0000000..113692d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00021.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00022.png b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00022.png new file mode 100644 index 0000000..1e1fd15 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00022.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00023.png b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00023.png new file mode 100644 index 0000000..4aba0a2 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_lock_then_transfer/00023.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00000.png b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00010.png b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00010.png new file mode 100644 index 0000000..52764e9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00011.png b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00011.png new file mode 100644 index 0000000..52764e9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00020.png b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00020.png new file mode 100644 index 0000000..575995c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00020.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00021.png b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00021.png new file mode 100644 index 0000000..5974993 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00021.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00022.png b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00022.png new file mode 100644 index 0000000..923e3f2 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00022.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00023.png b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00023.png new file mode 100644 index 0000000..e36e7a9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_mint_tokens/00023.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_conclude/00000.png b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_conclude/00010.png b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00010.png new file mode 100644 index 0000000..1b74062 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_conclude/00011.png b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00011.png new file mode 100644 index 0000000..1b74062 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_conclude/00020.png b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00020.png new file mode 100644 index 0000000..c7c92d0 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00020.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_conclude/00021.png b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00021.png new file mode 100644 index 0000000..c7c92d0 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00021.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_conclude/00030.png b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00030.png new file mode 100644 index 0000000..575995c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00030.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_conclude/00031.png b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00031.png new file mode 100644 index 0000000..113692d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00031.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_conclude/00032.png b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00032.png new file mode 100644 index 0000000..931b256 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00032.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_conclude/00033.png b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00033.png new file mode 100644 index 0000000..e36e7a9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_conclude/00033.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_fill/00000.png b/tests/snapshots/apex_p/test_sign_tx_order_fill/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_fill/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_fill/00010.png b/tests/snapshots/apex_p/test_sign_tx_order_fill/00010.png new file mode 100644 index 0000000..1d3567b Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_fill/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_fill/00011.png b/tests/snapshots/apex_p/test_sign_tx_order_fill/00011.png new file mode 100644 index 0000000..1d3567b Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_fill/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_fill/00020.png b/tests/snapshots/apex_p/test_sign_tx_order_fill/00020.png new file mode 100644 index 0000000..c2afd83 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_fill/00020.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_fill/00021.png b/tests/snapshots/apex_p/test_sign_tx_order_fill/00021.png new file mode 100644 index 0000000..c2afd83 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_fill/00021.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_fill/00030.png b/tests/snapshots/apex_p/test_sign_tx_order_fill/00030.png new file mode 100644 index 0000000..575995c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_fill/00030.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_fill/00031.png b/tests/snapshots/apex_p/test_sign_tx_order_fill/00031.png new file mode 100644 index 0000000..113692d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_fill/00031.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_fill/00032.png b/tests/snapshots/apex_p/test_sign_tx_order_fill/00032.png new file mode 100644 index 0000000..700876b Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_fill/00032.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_order_fill/00033.png b/tests/snapshots/apex_p/test_sign_tx_order_fill/00033.png new file mode 100644 index 0000000..e36e7a9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_order_fill/00033.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_transfer/00000.png b/tests/snapshots/apex_p/test_sign_tx_transfer/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_transfer/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_transfer/00010.png b/tests/snapshots/apex_p/test_sign_tx_transfer/00010.png new file mode 100644 index 0000000..25d533d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_transfer/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_transfer/00011.png b/tests/snapshots/apex_p/test_sign_tx_transfer/00011.png new file mode 100644 index 0000000..a9958ff Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_transfer/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_transfer/00012.png b/tests/snapshots/apex_p/test_sign_tx_transfer/00012.png new file mode 100644 index 0000000..4b44940 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_transfer/00012.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_transfer/00013.png b/tests/snapshots/apex_p/test_sign_tx_transfer/00013.png new file mode 100644 index 0000000..4aba0a2 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_transfer/00013.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00000.png b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00010.png b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00010.png new file mode 100644 index 0000000..5325934 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00011.png b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00011.png new file mode 100644 index 0000000..5325934 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00020.png b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00020.png new file mode 100644 index 0000000..bad1ebd Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00020.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00021.png b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00021.png new file mode 100644 index 0000000..113692d Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00021.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00022.png b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00022.png new file mode 100644 index 0000000..01174e8 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00022.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00023.png b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00023.png new file mode 100644 index 0000000..e36e7a9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unfreeze_tokens/00023.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00000.png b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00000.png new file mode 100644 index 0000000..f89ff1c Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00000.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00010.png b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00010.png new file mode 100644 index 0000000..f2b28cb Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00010.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00011.png b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00011.png new file mode 100644 index 0000000..f2b28cb Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00011.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00020.png b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00020.png new file mode 100644 index 0000000..bad1ebd Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00020.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00021.png b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00021.png new file mode 100644 index 0000000..896f1de Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00021.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00022.png b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00022.png new file mode 100644 index 0000000..f737ad3 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00022.png differ diff --git a/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00023.png b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00023.png new file mode 100644 index 0000000..e36e7a9 Binary files /dev/null and b/tests/snapshots/apex_p/test_sign_tx_unmint_tokens/00023.png differ diff --git a/tests/snapshots/flex/test_app_mainmenu/00000.png b/tests/snapshots/flex/test_app_mainmenu/00000.png new file mode 100644 index 0000000..f2fa972 Binary files /dev/null and b/tests/snapshots/flex/test_app_mainmenu/00000.png differ diff --git a/tests/snapshots/flex/test_app_mainmenu/00001.png b/tests/snapshots/flex/test_app_mainmenu/00001.png new file mode 100644 index 0000000..b3f1c85 Binary files /dev/null and b/tests/snapshots/flex/test_app_mainmenu/00001.png differ diff --git a/tests/snapshots/flex/test_app_mainmenu/00002.png b/tests/snapshots/flex/test_app_mainmenu/00002.png new file mode 100644 index 0000000..ad64488 Binary files /dev/null and b/tests/snapshots/flex/test_app_mainmenu/00002.png differ diff --git a/tests/snapshots/flex/test_app_mainmenu/00003.png b/tests/snapshots/flex/test_app_mainmenu/00003.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_app_mainmenu/00003.png differ diff --git a/tests/snapshots/flex/test_get_public_key_confirm_accepted/00000.png b/tests/snapshots/flex/test_get_public_key_confirm_accepted/00000.png new file mode 100644 index 0000000..22e90c6 Binary files /dev/null and b/tests/snapshots/flex/test_get_public_key_confirm_accepted/00000.png differ diff --git a/tests/snapshots/flex/test_get_public_key_confirm_accepted/00001.png b/tests/snapshots/flex/test_get_public_key_confirm_accepted/00001.png new file mode 100644 index 0000000..cf019b4 Binary files /dev/null and b/tests/snapshots/flex/test_get_public_key_confirm_accepted/00001.png differ diff --git a/tests/snapshots/flex/test_get_public_key_confirm_accepted/00002.png b/tests/snapshots/flex/test_get_public_key_confirm_accepted/00002.png new file mode 100644 index 0000000..8d07f2f Binary files /dev/null and b/tests/snapshots/flex/test_get_public_key_confirm_accepted/00002.png differ diff --git a/tests/snapshots/flex/test_get_public_key_confirm_accepted/00003.png b/tests/snapshots/flex/test_get_public_key_confirm_accepted/00003.png new file mode 100644 index 0000000..f2fa972 Binary files /dev/null and b/tests/snapshots/flex/test_get_public_key_confirm_accepted/00003.png differ diff --git a/tests/snapshots/flex/test_get_public_key_confirm_refused/00000.png b/tests/snapshots/flex/test_get_public_key_confirm_refused/00000.png new file mode 100644 index 0000000..22e90c6 Binary files /dev/null and b/tests/snapshots/flex/test_get_public_key_confirm_refused/00000.png differ diff --git a/tests/snapshots/flex/test_get_public_key_confirm_refused/00001.png b/tests/snapshots/flex/test_get_public_key_confirm_refused/00001.png new file mode 100644 index 0000000..cf019b4 Binary files /dev/null and b/tests/snapshots/flex/test_get_public_key_confirm_refused/00001.png differ diff --git a/tests/snapshots/flex/test_get_public_key_confirm_refused/00002.png b/tests/snapshots/flex/test_get_public_key_confirm_refused/00002.png new file mode 100644 index 0000000..7c8c42e Binary files /dev/null and b/tests/snapshots/flex/test_get_public_key_confirm_refused/00002.png differ diff --git a/tests/snapshots/flex/test_get_public_key_confirm_refused/00003.png b/tests/snapshots/flex/test_get_public_key_confirm_refused/00003.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_get_public_key_confirm_refused/00003.png differ diff --git a/tests/snapshots/flex/test_sign_message/00000.png b/tests/snapshots/flex/test_sign_message/00000.png new file mode 100644 index 0000000..ab24a07 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message/00000.png differ diff --git a/tests/snapshots/flex/test_sign_message/00001.png b/tests/snapshots/flex/test_sign_message/00001.png new file mode 100644 index 0000000..9abda3f Binary files /dev/null and b/tests/snapshots/flex/test_sign_message/00001.png differ diff --git a/tests/snapshots/flex/test_sign_message/00002.png b/tests/snapshots/flex/test_sign_message/00002.png new file mode 100644 index 0000000..3849275 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message/00002.png differ diff --git a/tests/snapshots/flex/test_sign_message/00003.png b/tests/snapshots/flex/test_sign_message/00003.png new file mode 100644 index 0000000..f8e68c8 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message/00003.png differ diff --git a/tests/snapshots/flex/test_sign_message/00004.png b/tests/snapshots/flex/test_sign_message/00004.png new file mode 100644 index 0000000..f2fa972 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message/00004.png differ diff --git a/tests/snapshots/flex/test_sign_message_pkh/00000.png b/tests/snapshots/flex/test_sign_message_pkh/00000.png new file mode 100644 index 0000000..ab24a07 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_pkh/00000.png differ diff --git a/tests/snapshots/flex/test_sign_message_pkh/00001.png b/tests/snapshots/flex/test_sign_message_pkh/00001.png new file mode 100644 index 0000000..d63bb87 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_pkh/00001.png differ diff --git a/tests/snapshots/flex/test_sign_message_pkh/00002.png b/tests/snapshots/flex/test_sign_message_pkh/00002.png new file mode 100644 index 0000000..3849275 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_pkh/00002.png differ diff --git a/tests/snapshots/flex/test_sign_message_pkh/00003.png b/tests/snapshots/flex/test_sign_message_pkh/00003.png new file mode 100644 index 0000000..f8e68c8 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_pkh/00003.png differ diff --git a/tests/snapshots/flex/test_sign_message_pkh/00004.png b/tests/snapshots/flex/test_sign_message_pkh/00004.png new file mode 100644 index 0000000..f2fa972 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_pkh/00004.png differ diff --git a/tests/snapshots/flex/test_sign_message_refused/00000.png b/tests/snapshots/flex/test_sign_message_refused/00000.png new file mode 100644 index 0000000..ab24a07 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_refused/00000.png differ diff --git a/tests/snapshots/flex/test_sign_message_refused/00001.png b/tests/snapshots/flex/test_sign_message_refused/00001.png new file mode 100644 index 0000000..9abda3f Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_refused/00001.png differ diff --git a/tests/snapshots/flex/test_sign_message_refused/00002.png b/tests/snapshots/flex/test_sign_message_refused/00002.png new file mode 100644 index 0000000..3849275 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_refused/00002.png differ diff --git a/tests/snapshots/flex/test_sign_message_refused/00003.png b/tests/snapshots/flex/test_sign_message_refused/00003.png new file mode 100644 index 0000000..19e8366 Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_refused/00003.png differ diff --git a/tests/snapshots/flex/test_sign_message_refused/00004.png b/tests/snapshots/flex/test_sign_message_refused/00004.png new file mode 100644 index 0000000..40eeaba Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_refused/00004.png differ diff --git a/tests/snapshots/flex/test_sign_message_refused/00005.png b/tests/snapshots/flex/test_sign_message_refused/00005.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_sign_message_refused/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00000.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00001.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00001.png new file mode 100644 index 0000000..a35c8fe Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00002.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00002.png new file mode 100644 index 0000000..f8cf440 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00003.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00003.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00004.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00004.png new file mode 100644 index 0000000..553394e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00010.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00010.png new file mode 100644 index 0000000..31ddc9e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00011.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00011.png new file mode 100644 index 0000000..31ddc9e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00020.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00020.png new file mode 100644 index 0000000..01b72a7 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00020.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00021.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00021.png new file mode 100644 index 0000000..8a8445e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00021.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00022.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00022.png new file mode 100644 index 0000000..68f59e1 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00022.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_authority/00023.png b/tests/snapshots/flex/test_sign_tx_change_token_authority/00023.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_authority/00023.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00000.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00001.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00001.png new file mode 100644 index 0000000..a35c8fe Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00002.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00002.png new file mode 100644 index 0000000..3d2dbe5 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00003.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00003.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00004.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00004.png new file mode 100644 index 0000000..553394e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00010.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00010.png new file mode 100644 index 0000000..51ab425 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00011.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00011.png new file mode 100644 index 0000000..51ab425 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00020.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00020.png new file mode 100644 index 0000000..01b72a7 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00020.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00021.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00021.png new file mode 100644 index 0000000..8a8445e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00021.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00022.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00022.png new file mode 100644 index 0000000..bcf4b40 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00022.png differ diff --git a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00023.png b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00023.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00023.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_delegation/00000.png b/tests/snapshots/flex/test_sign_tx_create_delegation/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_delegation/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_delegation/00001.png b/tests/snapshots/flex/test_sign_tx_create_delegation/00001.png new file mode 100644 index 0000000..22a1f7f Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_delegation/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_delegation/00002.png b/tests/snapshots/flex/test_sign_tx_create_delegation/00002.png new file mode 100644 index 0000000..9a4e534 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_delegation/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_delegation/00003.png b/tests/snapshots/flex/test_sign_tx_create_delegation/00003.png new file mode 100644 index 0000000..2fa6cf6 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_delegation/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_delegation/00004.png b/tests/snapshots/flex/test_sign_tx_create_delegation/00004.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_delegation/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_delegation/00005.png b/tests/snapshots/flex/test_sign_tx_create_delegation/00005.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_delegation/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_delegation/00010.png b/tests/snapshots/flex/test_sign_tx_create_delegation/00010.png new file mode 100644 index 0000000..428cd7e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_delegation/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_delegation/00011.png b/tests/snapshots/flex/test_sign_tx_create_delegation/00011.png new file mode 100644 index 0000000..bdfc1af Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_delegation/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_delegation/00012.png b/tests/snapshots/flex/test_sign_tx_create_delegation/00012.png new file mode 100644 index 0000000..48c4ef2 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_delegation/00012.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_delegation/00013.png b/tests/snapshots/flex/test_sign_tx_create_delegation/00013.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_delegation/00013.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00000.png b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00001.png b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00001.png new file mode 100644 index 0000000..4477f6e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00002.png b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00002.png new file mode 100644 index 0000000..780f8bd Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00003.png b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00003.png new file mode 100644 index 0000000..da03051 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00004.png b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00004.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00005.png b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00005.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00010.png b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00010.png new file mode 100644 index 0000000..d5b69b4 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00011.png b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00011.png new file mode 100644 index 0000000..8a8445e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00012.png b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00012.png new file mode 100644 index 0000000..c6b89cb Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00012.png differ diff --git a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00013.png b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00013.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_create_stake_pool/00013.png differ diff --git a/tests/snapshots/flex/test_sign_tx_delegation_staking/00000.png b/tests/snapshots/flex/test_sign_tx_delegation_staking/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_delegation_staking/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_delegation_staking/00001.png b/tests/snapshots/flex/test_sign_tx_delegation_staking/00001.png new file mode 100644 index 0000000..77e8ab2 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_delegation_staking/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_delegation_staking/00002.png b/tests/snapshots/flex/test_sign_tx_delegation_staking/00002.png new file mode 100644 index 0000000..93e8caf Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_delegation_staking/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_delegation_staking/00003.png b/tests/snapshots/flex/test_sign_tx_delegation_staking/00003.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_delegation_staking/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_delegation_staking/00004.png b/tests/snapshots/flex/test_sign_tx_delegation_staking/00004.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_delegation_staking/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_delegation_staking/00010.png b/tests/snapshots/flex/test_sign_tx_delegation_staking/00010.png new file mode 100644 index 0000000..d559d03 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_delegation_staking/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_delegation_staking/00011.png b/tests/snapshots/flex/test_sign_tx_delegation_staking/00011.png new file mode 100644 index 0000000..51e3005 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_delegation_staking/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_delegation_staking/00012.png b/tests/snapshots/flex/test_sign_tx_delegation_staking/00012.png new file mode 100644 index 0000000..0214b02 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_delegation_staking/00012.png differ diff --git a/tests/snapshots/flex/test_sign_tx_delegation_staking/00013.png b/tests/snapshots/flex/test_sign_tx_delegation_staking/00013.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_delegation_staking/00013.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00000.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00001.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00001.png new file mode 100644 index 0000000..a35c8fe Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00002.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00002.png new file mode 100644 index 0000000..4a5b80c Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00003.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00003.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00004.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00004.png new file mode 100644 index 0000000..553394e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00010.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00010.png new file mode 100644 index 0000000..f156168 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00011.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00011.png new file mode 100644 index 0000000..f156168 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00020.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00020.png new file mode 100644 index 0000000..01b72a7 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00020.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00021.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00021.png new file mode 100644 index 0000000..8a8445e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00021.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00022.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00022.png new file mode 100644 index 0000000..aa0f0aa Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00022.png differ diff --git a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00023.png b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00023.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00023.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00000.png b/tests/snapshots/flex/test_sign_tx_htlc/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00001.png b/tests/snapshots/flex/test_sign_tx_htlc/00001.png new file mode 100644 index 0000000..f2dcdf5 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00002.png b/tests/snapshots/flex/test_sign_tx_htlc/00002.png new file mode 100644 index 0000000..fa66a8a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00003.png b/tests/snapshots/flex/test_sign_tx_htlc/00003.png new file mode 100644 index 0000000..da95e9c Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00004.png b/tests/snapshots/flex/test_sign_tx_htlc/00004.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00005.png b/tests/snapshots/flex/test_sign_tx_htlc/00005.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00010.png b/tests/snapshots/flex/test_sign_tx_htlc/00010.png new file mode 100644 index 0000000..26ad42d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00011.png b/tests/snapshots/flex/test_sign_tx_htlc/00011.png new file mode 100644 index 0000000..26ad42d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00020.png b/tests/snapshots/flex/test_sign_tx_htlc/00020.png new file mode 100644 index 0000000..ddbc1a4 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00020.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00021.png b/tests/snapshots/flex/test_sign_tx_htlc/00021.png new file mode 100644 index 0000000..8a8445e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00021.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00022.png b/tests/snapshots/flex/test_sign_tx_htlc/00022.png new file mode 100644 index 0000000..77f2381 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00022.png differ diff --git a/tests/snapshots/flex/test_sign_tx_htlc/00023.png b/tests/snapshots/flex/test_sign_tx_htlc/00023.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_htlc/00023.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00000.png b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00001.png b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00001.png new file mode 100644 index 0000000..06c369e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00002.png b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00002.png new file mode 100644 index 0000000..9a4e534 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00003.png b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00003.png new file mode 100644 index 0000000..3babddd Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00004.png b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00004.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00005.png b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00005.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00010.png b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00010.png new file mode 100644 index 0000000..959e4d1 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00011.png b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00011.png new file mode 100644 index 0000000..bdfc1af Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00012.png b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00012.png new file mode 100644 index 0000000..55dce88 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00012.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00013.png b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00013.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00013.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_nft/00000.png b/tests/snapshots/flex/test_sign_tx_issue_nft/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_nft/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_nft/00001.png b/tests/snapshots/flex/test_sign_tx_issue_nft/00001.png new file mode 100644 index 0000000..f7f99ec Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_nft/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_nft/00002.png b/tests/snapshots/flex/test_sign_tx_issue_nft/00002.png new file mode 100644 index 0000000..36cc105 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_nft/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_nft/00003.png b/tests/snapshots/flex/test_sign_tx_issue_nft/00003.png new file mode 100644 index 0000000..2d3241f Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_nft/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_nft/00004.png b/tests/snapshots/flex/test_sign_tx_issue_nft/00004.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_nft/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_nft/00005.png b/tests/snapshots/flex/test_sign_tx_issue_nft/00005.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_nft/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_nft/00010.png b/tests/snapshots/flex/test_sign_tx_issue_nft/00010.png new file mode 100644 index 0000000..78a5ee8 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_nft/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_nft/00011.png b/tests/snapshots/flex/test_sign_tx_issue_nft/00011.png new file mode 100644 index 0000000..c77916a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_nft/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_nft/00012.png b/tests/snapshots/flex/test_sign_tx_issue_nft/00012.png new file mode 100644 index 0000000..b1edb3e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_nft/00012.png differ diff --git a/tests/snapshots/flex/test_sign_tx_issue_nft/00013.png b/tests/snapshots/flex/test_sign_tx_issue_nft/00013.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_issue_nft/00013.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00000.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00001.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00001.png new file mode 100644 index 0000000..8a8445e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00002.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00002.png new file mode 100644 index 0000000..d0597b4 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00003.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00003.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00004.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00004.png new file mode 100644 index 0000000..f2fa972 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00005.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00005.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00010.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00010.png new file mode 100644 index 0000000..53b5831 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00011.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00011.png new file mode 100644 index 0000000..53b5831 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00012.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00012.png new file mode 100644 index 0000000..bb4b77a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00012.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00020.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00020.png new file mode 100644 index 0000000..484200d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00020.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00021.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00021.png new file mode 100644 index 0000000..8a8445e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00021.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00022.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00022.png new file mode 100644 index 0000000..d0597b4 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00022.png differ diff --git a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00023.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00023.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00023.png differ diff --git a/tests/snapshots/flex/test_sign_tx_long_tx/00000.png b/tests/snapshots/flex/test_sign_tx_long_tx/00000.png new file mode 100644 index 0000000..0649145 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_long_tx/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_long_tx/00001.png b/tests/snapshots/flex/test_sign_tx_long_tx/00001.png new file mode 100644 index 0000000..fa1a974 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_long_tx/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_long_tx/00002.png b/tests/snapshots/flex/test_sign_tx_long_tx/00002.png new file mode 100644 index 0000000..ff0fd44 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_long_tx/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_long_tx/00003.png b/tests/snapshots/flex/test_sign_tx_long_tx/00003.png new file mode 100644 index 0000000..fd33e09 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_long_tx/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_long_tx/00004.png b/tests/snapshots/flex/test_sign_tx_long_tx/00004.png new file mode 100644 index 0000000..be51a9d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_long_tx/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_long_tx/00005.png b/tests/snapshots/flex/test_sign_tx_long_tx/00005.png new file mode 100644 index 0000000..8a9212d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_long_tx/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00000.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00001.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00001.png new file mode 100644 index 0000000..a7e344d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00002.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00002.png new file mode 100644 index 0000000..82d6a13 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00003.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00003.png new file mode 100644 index 0000000..55d938e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00004.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00004.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00005.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00005.png new file mode 100644 index 0000000..553394e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00010.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00010.png new file mode 100644 index 0000000..eb4eae4 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00011.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00011.png new file mode 100644 index 0000000..eb4eae4 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00020.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00020.png new file mode 100644 index 0000000..bfbc477 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00020.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00021.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00021.png new file mode 100644 index 0000000..9882d41 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00021.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00022.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00022.png new file mode 100644 index 0000000..ad35bf1 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00022.png differ diff --git a/tests/snapshots/flex/test_sign_tx_mint_tokens/00023.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00023.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00023.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00000.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00001.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00001.png new file mode 100644 index 0000000..b27ad50 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00002.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00002.png new file mode 100644 index 0000000..f198ed6 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00003.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00003.png new file mode 100644 index 0000000..5c9b386 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00004.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00004.png new file mode 100644 index 0000000..3ab6bae Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00005.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00005.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00006.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00006.png new file mode 100644 index 0000000..553394e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00006.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00010.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00010.png new file mode 100644 index 0000000..08d878b Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00011.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00011.png new file mode 100644 index 0000000..08d878b Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00020.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00020.png new file mode 100644 index 0000000..da876bd Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00020.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00021.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00021.png new file mode 100644 index 0000000..da876bd Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00021.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00030.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00030.png new file mode 100644 index 0000000..b43304b Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00030.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00031.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00031.png new file mode 100644 index 0000000..8a8445e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00031.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00032.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00032.png new file mode 100644 index 0000000..f4f3a10 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00032.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_conclude/00033.png b/tests/snapshots/flex/test_sign_tx_order_conclude/00033.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_conclude/00033.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00000.png b/tests/snapshots/flex/test_sign_tx_order_fill/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00001.png b/tests/snapshots/flex/test_sign_tx_order_fill/00001.png new file mode 100644 index 0000000..7657c0b Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00002.png b/tests/snapshots/flex/test_sign_tx_order_fill/00002.png new file mode 100644 index 0000000..d67d882 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00003.png b/tests/snapshots/flex/test_sign_tx_order_fill/00003.png new file mode 100644 index 0000000..5c9b386 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00004.png b/tests/snapshots/flex/test_sign_tx_order_fill/00004.png new file mode 100644 index 0000000..4e3f52b Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00005.png b/tests/snapshots/flex/test_sign_tx_order_fill/00005.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00006.png b/tests/snapshots/flex/test_sign_tx_order_fill/00006.png new file mode 100644 index 0000000..553394e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00006.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00010.png b/tests/snapshots/flex/test_sign_tx_order_fill/00010.png new file mode 100644 index 0000000..b613574 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00011.png b/tests/snapshots/flex/test_sign_tx_order_fill/00011.png new file mode 100644 index 0000000..b613574 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00020.png b/tests/snapshots/flex/test_sign_tx_order_fill/00020.png new file mode 100644 index 0000000..ddbc1a4 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00020.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00021.png b/tests/snapshots/flex/test_sign_tx_order_fill/00021.png new file mode 100644 index 0000000..ddbc1a4 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00021.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00030.png b/tests/snapshots/flex/test_sign_tx_order_fill/00030.png new file mode 100644 index 0000000..08604b0 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00030.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00031.png b/tests/snapshots/flex/test_sign_tx_order_fill/00031.png new file mode 100644 index 0000000..8a8445e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00031.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00032.png b/tests/snapshots/flex/test_sign_tx_order_fill/00032.png new file mode 100644 index 0000000..5b7bcb1 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00032.png differ diff --git a/tests/snapshots/flex/test_sign_tx_order_fill/00033.png b/tests/snapshots/flex/test_sign_tx_order_fill/00033.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_order_fill/00033.png differ diff --git a/tests/snapshots/flex/test_sign_tx_refused/00000.png b/tests/snapshots/flex/test_sign_tx_refused/00000.png new file mode 100644 index 0000000..c2a4a2f Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_refused/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_refused/00001.png b/tests/snapshots/flex/test_sign_tx_refused/00001.png new file mode 100644 index 0000000..5d919f7 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_refused/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_refused/00002.png b/tests/snapshots/flex/test_sign_tx_refused/00002.png new file mode 100644 index 0000000..9a270f5 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_refused/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_refused/00003.png b/tests/snapshots/flex/test_sign_tx_refused/00003.png new file mode 100644 index 0000000..6a11e11 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_refused/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_refused/00004.png b/tests/snapshots/flex/test_sign_tx_refused/00004.png new file mode 100644 index 0000000..6bbdf2f Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_refused/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_refused/00005.png b/tests/snapshots/flex/test_sign_tx_refused/00005.png new file mode 100644 index 0000000..8a9212d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_refused/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx/00000.png b/tests/snapshots/flex/test_sign_tx_short_tx/00000.png new file mode 100644 index 0000000..d60a071 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx/00001.png b/tests/snapshots/flex/test_sign_tx_short_tx/00001.png new file mode 100644 index 0000000..fe24a7b Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx/00002.png b/tests/snapshots/flex/test_sign_tx_short_tx/00002.png new file mode 100644 index 0000000..7752e76 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx/00003.png b/tests/snapshots/flex/test_sign_tx_short_tx/00003.png new file mode 100644 index 0000000..6d18dff Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx/00004.png b/tests/snapshots/flex/test_sign_tx_short_tx/00004.png new file mode 100644 index 0000000..be51a9d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx/00005.png b/tests/snapshots/flex/test_sign_tx_short_tx/00005.png new file mode 100644 index 0000000..ca1717c Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00000.png b/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00000.png new file mode 100644 index 0000000..c2a4a2f Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00001.png b/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00001.png new file mode 100644 index 0000000..2d0c474 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00002.png b/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00002.png new file mode 100644 index 0000000..9a270f5 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00003.png b/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00003.png new file mode 100644 index 0000000..be51a9d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00004.png b/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00004.png new file mode 100644 index 0000000..8a9212d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_no_memo/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_transfer/00000.png b/tests/snapshots/flex/test_sign_tx_transfer/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_transfer/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_transfer/00001.png b/tests/snapshots/flex/test_sign_tx_transfer/00001.png new file mode 100644 index 0000000..67a9b5a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_transfer/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_transfer/00002.png b/tests/snapshots/flex/test_sign_tx_transfer/00002.png new file mode 100644 index 0000000..77025cd Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_transfer/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_transfer/00003.png b/tests/snapshots/flex/test_sign_tx_transfer/00003.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_transfer/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_transfer/00004.png b/tests/snapshots/flex/test_sign_tx_transfer/00004.png new file mode 100644 index 0000000..f2fa972 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_transfer/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_transfer/00005.png b/tests/snapshots/flex/test_sign_tx_transfer/00005.png new file mode 100644 index 0000000..c0e88bb Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_transfer/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_transfer/00010.png b/tests/snapshots/flex/test_sign_tx_transfer/00010.png new file mode 100644 index 0000000..016f0ec Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_transfer/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_transfer/00011.png b/tests/snapshots/flex/test_sign_tx_transfer/00011.png new file mode 100644 index 0000000..67a9b5a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_transfer/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_transfer/00012.png b/tests/snapshots/flex/test_sign_tx_transfer/00012.png new file mode 100644 index 0000000..77025cd Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_transfer/00012.png differ diff --git a/tests/snapshots/flex/test_sign_tx_transfer/00013.png b/tests/snapshots/flex/test_sign_tx_transfer/00013.png new file mode 100644 index 0000000..435aa78 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_transfer/00013.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00000.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00001.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00001.png new file mode 100644 index 0000000..a35c8fe Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00002.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00002.png new file mode 100644 index 0000000..06b6496 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00003.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00003.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00004.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00004.png new file mode 100644 index 0000000..553394e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00010.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00010.png new file mode 100644 index 0000000..92acded Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00011.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00011.png new file mode 100644 index 0000000..92acded Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00020.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00020.png new file mode 100644 index 0000000..01b72a7 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00020.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00021.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00021.png new file mode 100644 index 0000000..8a8445e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00021.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00022.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00022.png new file mode 100644 index 0000000..5a46298 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00022.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00023.png b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00023.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00023.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00000.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00000.png new file mode 100644 index 0000000..5d42a9a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00001.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00001.png new file mode 100644 index 0000000..d8a9bad Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00002.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00002.png new file mode 100644 index 0000000..7a34a97 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00003.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00003.png new file mode 100644 index 0000000..a3c1ec1 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00004.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00004.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00005.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00005.png new file mode 100644 index 0000000..553394e Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00005.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00010.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00010.png new file mode 100644 index 0000000..a0aa228 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00010.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00011.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00011.png new file mode 100644 index 0000000..a0aa228 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00011.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00020.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00020.png new file mode 100644 index 0000000..01b72a7 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00020.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00021.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00021.png new file mode 100644 index 0000000..2d9e0a0 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00021.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00022.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00022.png new file mode 100644 index 0000000..62478ed Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00022.png differ diff --git a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00023.png b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00023.png new file mode 100644 index 0000000..9f79b05 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00023.png differ diff --git a/tests/snapshots/nanosp/test_app_mainmenu/00000.png b/tests/snapshots/nanosp/test_app_mainmenu/00000.png new file mode 100644 index 0000000..4073303 Binary files /dev/null and b/tests/snapshots/nanosp/test_app_mainmenu/00000.png differ diff --git a/tests/snapshots/nanosp/test_app_mainmenu/00001.png b/tests/snapshots/nanosp/test_app_mainmenu/00001.png new file mode 100644 index 0000000..77bcafd Binary files /dev/null and b/tests/snapshots/nanosp/test_app_mainmenu/00001.png differ diff --git a/tests/snapshots/nanosp/test_app_mainmenu/00002.png b/tests/snapshots/nanosp/test_app_mainmenu/00002.png new file mode 100644 index 0000000..f265d69 Binary files /dev/null and b/tests/snapshots/nanosp/test_app_mainmenu/00002.png differ diff --git a/tests/snapshots/nanosp/test_app_mainmenu/00003.png b/tests/snapshots/nanosp/test_app_mainmenu/00003.png new file mode 100644 index 0000000..f265d69 Binary files /dev/null and b/tests/snapshots/nanosp/test_app_mainmenu/00003.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00000.png b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00000.png new file mode 100644 index 0000000..e2ead08 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00000.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00001.png b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00001.png new file mode 100644 index 0000000..602c22a Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00001.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00002.png b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00002.png new file mode 100644 index 0000000..305308f Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00002.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00003.png b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00003.png new file mode 100644 index 0000000..7dfa0c5 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00003.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00004.png b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00004.png new file mode 100644 index 0000000..84caa59 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00004.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00005.png b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00005.png new file mode 100644 index 0000000..32e7443 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00005.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00006.png b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00006.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_accepted/00006.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00000.png b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00000.png new file mode 100644 index 0000000..e2ead08 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00000.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00001.png b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00001.png new file mode 100644 index 0000000..602c22a Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00001.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00002.png b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00002.png new file mode 100644 index 0000000..305308f Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00002.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00003.png b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00003.png new file mode 100644 index 0000000..7dfa0c5 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00003.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00004.png b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00004.png new file mode 100644 index 0000000..7b38f99 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00004.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00005.png b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00005.png new file mode 100644 index 0000000..03e5ee2 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00005.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00006.png b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00006.png new file mode 100644 index 0000000..fbfed86 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00006.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00007.png b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00007.png new file mode 100644 index 0000000..bdbc0ff Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00007.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00008.png b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00008.png new file mode 100644 index 0000000..77bcafd Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00008.png differ diff --git a/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00009.png b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00009.png new file mode 100644 index 0000000..f265d69 Binary files /dev/null and b/tests/snapshots/nanosp/test_get_public_key_confirm_refused/00009.png differ diff --git a/tests/snapshots/nanosp/test_sign_message/00000.png b/tests/snapshots/nanosp/test_sign_message/00000.png new file mode 100644 index 0000000..2e4d511 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_message/00001.png b/tests/snapshots/nanosp/test_sign_message/00001.png new file mode 100644 index 0000000..8cae4d6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_message/00002.png b/tests/snapshots/nanosp/test_sign_message/00002.png new file mode 100644 index 0000000..602c22a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_message/00003.png b/tests/snapshots/nanosp/test_sign_message/00003.png new file mode 100644 index 0000000..305308f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_message/00004.png b/tests/snapshots/nanosp/test_sign_message/00004.png new file mode 100644 index 0000000..3617b8d Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_message/00005.png b/tests/snapshots/nanosp/test_sign_message/00005.png new file mode 100644 index 0000000..55bb5c8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_message/00006.png b/tests/snapshots/nanosp/test_sign_message/00006.png new file mode 100644 index 0000000..ab20bae Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_pkh/00000.png b/tests/snapshots/nanosp/test_sign_message_pkh/00000.png new file mode 100644 index 0000000..2e4d511 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_pkh/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_pkh/00001.png b/tests/snapshots/nanosp/test_sign_message_pkh/00001.png new file mode 100644 index 0000000..8cae4d6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_pkh/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_pkh/00002.png b/tests/snapshots/nanosp/test_sign_message_pkh/00002.png new file mode 100644 index 0000000..208f5d8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_pkh/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_pkh/00003.png b/tests/snapshots/nanosp/test_sign_message_pkh/00003.png new file mode 100644 index 0000000..3617b8d Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_pkh/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_pkh/00004.png b/tests/snapshots/nanosp/test_sign_message_pkh/00004.png new file mode 100644 index 0000000..55bb5c8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_pkh/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_pkh/00005.png b/tests/snapshots/nanosp/test_sign_message_pkh/00005.png new file mode 100644 index 0000000..ab20bae Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_pkh/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_refused/00000.png b/tests/snapshots/nanosp/test_sign_message_refused/00000.png new file mode 100644 index 0000000..2e4d511 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_refused/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_refused/00001.png b/tests/snapshots/nanosp/test_sign_message_refused/00001.png new file mode 100644 index 0000000..8cae4d6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_refused/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_refused/00002.png b/tests/snapshots/nanosp/test_sign_message_refused/00002.png new file mode 100644 index 0000000..602c22a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_refused/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_refused/00003.png b/tests/snapshots/nanosp/test_sign_message_refused/00003.png new file mode 100644 index 0000000..305308f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_refused/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_refused/00004.png b/tests/snapshots/nanosp/test_sign_message_refused/00004.png new file mode 100644 index 0000000..3617b8d Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_refused/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_refused/00005.png b/tests/snapshots/nanosp/test_sign_message_refused/00005.png new file mode 100644 index 0000000..55bb5c8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_refused/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_refused/00006.png b/tests/snapshots/nanosp/test_sign_message_refused/00006.png new file mode 100644 index 0000000..12caa58 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_refused/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_message_refused/00007.png b/tests/snapshots/nanosp/test_sign_message_refused/00007.png new file mode 100644 index 0000000..d917d19 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_message_refused/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00000.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00001.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00002.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00002.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00003.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00003.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00004.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00004.png new file mode 100644 index 0000000..2fca943 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00005.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00005.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00006.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00006.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00010.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00010.png new file mode 100644 index 0000000..c408134 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00011.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00011.png new file mode 100644 index 0000000..fc6fca6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00012.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00012.png new file mode 100644 index 0000000..e2577f8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00013.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00013.png new file mode 100644 index 0000000..aa75038 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00013.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00020.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00021.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00022.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00022.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00023.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00023.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00024.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00024.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00024.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00025.png b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00025.png new file mode 100644 index 0000000..c81329e Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_authority/00025.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00000.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00001.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00002.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00002.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00003.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00003.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00004.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00004.png new file mode 100644 index 0000000..c7d5676 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00005.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00005.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00006.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00006.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00010.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00010.png new file mode 100644 index 0000000..de18f19 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00011.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00011.png new file mode 100644 index 0000000..39359b8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00012.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00012.png new file mode 100644 index 0000000..c335313 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00020.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00021.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00022.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00022.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00023.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00023.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00024.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00024.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00024.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00025.png b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00025.png new file mode 100644 index 0000000..d3f5cd6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_change_token_metadata_uri/00025.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00000.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00001.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00001.png new file mode 100644 index 0000000..59d0e80 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00002.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00002.png new file mode 100644 index 0000000..3d01046 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00003.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00003.png new file mode 100644 index 0000000..f62cce2 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00004.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00004.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00005.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00005.png new file mode 100644 index 0000000..0f6ca54 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00006.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00006.png new file mode 100644 index 0000000..17cf916 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00007.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00007.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00008.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00008.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00008.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00010.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00010.png new file mode 100644 index 0000000..7c23f06 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00011.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00011.png new file mode 100644 index 0000000..59d0e80 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00012.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00012.png new file mode 100644 index 0000000..3d01046 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00013.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00013.png new file mode 100644 index 0000000..f62cce2 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00013.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00014.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00014.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00014.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00015.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00015.png new file mode 100644 index 0000000..0f6ca54 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00015.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00016.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00016.png new file mode 100644 index 0000000..17cf916 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00016.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00000.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00001.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00001.png new file mode 100644 index 0000000..3fbfcda Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00002.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00002.png new file mode 100644 index 0000000..dc3f263 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00003.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00003.png new file mode 100644 index 0000000..dd49ec2 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00004.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00004.png new file mode 100644 index 0000000..7623766 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00005.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00005.png new file mode 100644 index 0000000..0562b8b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00006.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00006.png new file mode 100644 index 0000000..9880fbf Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00007.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00007.png new file mode 100644 index 0000000..5d19c53 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00008.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00008.png new file mode 100644 index 0000000..7184c47 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00008.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00009.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00009.png new file mode 100644 index 0000000..f278bff Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00009.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00010.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00010.png new file mode 100644 index 0000000..139058c Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00011.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00011.png new file mode 100644 index 0000000..dc3f263 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00012.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00012.png new file mode 100644 index 0000000..dd49ec2 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00013.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00013.png new file mode 100644 index 0000000..7623766 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00013.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00014.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00014.png new file mode 100644 index 0000000..0562b8b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00014.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00015.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00015.png new file mode 100644 index 0000000..9880fbf Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00015.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00016.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00016.png new file mode 100644 index 0000000..5d19c53 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00016.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00017.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00017.png new file mode 100644 index 0000000..7184c47 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00017.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00018.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00018.png new file mode 100644 index 0000000..f278bff Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00018.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00019.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00019.png new file mode 100644 index 0000000..06704db Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00019.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00020.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00021.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00021.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00022.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00022.png new file mode 100644 index 0000000..b3afad9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00000.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00001.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00001.png new file mode 100644 index 0000000..3645243 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00002.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00002.png new file mode 100644 index 0000000..2df9d67 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00003.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00003.png new file mode 100644 index 0000000..0623b1b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00004.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00004.png new file mode 100644 index 0000000..bbd76c8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00005.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00005.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00006.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00006.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00010.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00010.png new file mode 100644 index 0000000..15001c0 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00011.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00011.png new file mode 100644 index 0000000..52979b5 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00012.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00012.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00013.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00013.png new file mode 100644 index 0000000..0623b1b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00013.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00014.png b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00014.png new file mode 100644 index 0000000..c6836c8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_delegation_staking/00014.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00000.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00001.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00002.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00002.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00003.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00003.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00004.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00004.png new file mode 100644 index 0000000..bc9b1a8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00005.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00005.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00006.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00006.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00010.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00010.png new file mode 100644 index 0000000..eaa64e5 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00011.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00011.png new file mode 100644 index 0000000..351a884 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00020.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00021.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00022.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00022.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00023.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00023.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00024.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00024.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00024.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00025.png b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00025.png new file mode 100644 index 0000000..567675f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_freeze_tokens/00025.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00000.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00001.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00001.png new file mode 100644 index 0000000..aab0aed Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00002.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00002.png new file mode 100644 index 0000000..f113d41 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00003.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00003.png new file mode 100644 index 0000000..195e6f3 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00004.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00004.png new file mode 100644 index 0000000..778f66f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00005.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00005.png new file mode 100644 index 0000000..0d5d509 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00006.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00006.png new file mode 100644 index 0000000..5fc12d1 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00007.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00007.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00008.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00008.png new file mode 100644 index 0000000..62b7685 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00008.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00009.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00009.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00009.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00010.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00010.png new file mode 100644 index 0000000..40b1181 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00011.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00011.png new file mode 100644 index 0000000..f113d41 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00012.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00012.png new file mode 100644 index 0000000..195e6f3 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00013.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00013.png new file mode 100644 index 0000000..778f66f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00013.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00014.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00014.png new file mode 100644 index 0000000..0d5d509 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00014.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00015.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00015.png new file mode 100644 index 0000000..5fc12d1 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00015.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00020.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00021.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00022.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00022.png new file mode 100644 index 0000000..62b7685 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00023.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00023.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00024.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00024.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00024.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_htlc/00025.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00025.png new file mode 100644 index 0000000..32f349e Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_htlc/00025.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00000.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00001.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00001.png new file mode 100644 index 0000000..00051f8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00002.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00002.png new file mode 100644 index 0000000..c09832c Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00003.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00003.png new file mode 100644 index 0000000..419f5f0 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00004.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00004.png new file mode 100644 index 0000000..26db145 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00005.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00005.png new file mode 100644 index 0000000..060d61b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00006.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00006.png new file mode 100644 index 0000000..0f6ca54 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00007.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00007.png new file mode 100644 index 0000000..d3ca23a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00008.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00008.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00008.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00009.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00009.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00009.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00010.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00010.png new file mode 100644 index 0000000..7c86f79 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00011.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00011.png new file mode 100644 index 0000000..7f8fb9a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00012.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00012.png new file mode 100644 index 0000000..7cd6829 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00013.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00013.png new file mode 100644 index 0000000..6d1bc9a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00013.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00014.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00014.png new file mode 100644 index 0000000..4c43c01 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00014.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00015.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00015.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00015.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00016.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00016.png new file mode 100644 index 0000000..0f6ca54 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00016.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00017.png b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00017.png new file mode 100644 index 0000000..caaaca0 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_fungible_token/00017.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00000.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00001.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00001.png new file mode 100644 index 0000000..2318573 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00002.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00002.png new file mode 100644 index 0000000..d84fdcd Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00003.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00003.png new file mode 100644 index 0000000..415b46b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00004.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00004.png new file mode 100644 index 0000000..7fb1f67 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00005.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00005.png new file mode 100644 index 0000000..e14acb6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00006.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00006.png new file mode 100644 index 0000000..03f61f6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00007.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00007.png new file mode 100644 index 0000000..f678edc Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00008.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00008.png new file mode 100644 index 0000000..0a262d5 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00008.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00009.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00009.png new file mode 100644 index 0000000..1a586fb Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00009.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00010.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00010.png new file mode 100644 index 0000000..84ff3f7 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00011.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00011.png new file mode 100644 index 0000000..3fdec7f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00012.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00012.png new file mode 100644 index 0000000..a9bd3e2 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00013.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00013.png new file mode 100644 index 0000000..b9a3aba Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00013.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00014.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00014.png new file mode 100644 index 0000000..b69697c Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00014.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00015.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00015.png new file mode 100644 index 0000000..651a3f4 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00015.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00016.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00016.png new file mode 100644 index 0000000..19e1140 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00016.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00017.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00017.png new file mode 100644 index 0000000..95bb380 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00017.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00018.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00018.png new file mode 100644 index 0000000..4cf446c Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00018.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00019.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00019.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00019.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00020.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00020.png new file mode 100644 index 0000000..af149c9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00021.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00021.png new file mode 100644 index 0000000..8a6f6ed Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00000.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00001.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00001.png new file mode 100644 index 0000000..7a9b805 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00002.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00002.png new file mode 100644 index 0000000..342974f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00003.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00003.png new file mode 100644 index 0000000..a8a6913 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00004.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00004.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00005.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00005.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00006.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00006.png new file mode 100644 index 0000000..b00f750 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00007.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00007.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00010.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00010.png new file mode 100644 index 0000000..ac31f5f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00011.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00011.png new file mode 100644 index 0000000..b0f6c80 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00012.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00012.png new file mode 100644 index 0000000..eb0ade6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00013.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00013.png new file mode 100644 index 0000000..5204bce Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00013.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00020.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00021.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00021.png new file mode 100644 index 0000000..7a9b805 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00022.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00022.png new file mode 100644 index 0000000..342974f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00023.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00023.png new file mode 100644 index 0000000..a8a6913 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00023.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00024.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00024.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00024.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00025.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00025.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00025.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00026.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00026.png new file mode 100644 index 0000000..b00f750 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00026.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_long_tx/00000.png b/tests/snapshots/nanosp/test_sign_tx_long_tx/00000.png new file mode 100644 index 0000000..1597f7e Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_long_tx/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_long_tx/00001.png b/tests/snapshots/nanosp/test_sign_tx_long_tx/00001.png new file mode 100644 index 0000000..8a3938b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_long_tx/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_long_tx/00002.png b/tests/snapshots/nanosp/test_sign_tx_long_tx/00002.png new file mode 100644 index 0000000..8b3c9da Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_long_tx/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_long_tx/00003.png b/tests/snapshots/nanosp/test_sign_tx_long_tx/00003.png new file mode 100644 index 0000000..4a2929d Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_long_tx/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_long_tx/00004.png b/tests/snapshots/nanosp/test_sign_tx_long_tx/00004.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_long_tx/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00000.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00001.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00001.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00002.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00002.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00003.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00003.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00004.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00004.png new file mode 100644 index 0000000..2b9bccd Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00005.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00005.png new file mode 100644 index 0000000..eeaad30 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00006.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00006.png new file mode 100644 index 0000000..b807f41 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00007.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00007.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00008.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00008.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00008.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00010.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00010.png new file mode 100644 index 0000000..05bd21a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00011.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00011.png new file mode 100644 index 0000000..50fb1e2 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00012.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00012.png new file mode 100644 index 0000000..51c42bd Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00020.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00021.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00021.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00022.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00022.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00023.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00023.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00023.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00024.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00024.png new file mode 100644 index 0000000..2b9bccd Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00024.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00025.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00025.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00025.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00026.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00026.png new file mode 100644 index 0000000..eeaad30 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00026.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00027.png b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00027.png new file mode 100644 index 0000000..f2eaa31 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_mint_tokens/00027.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00000.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00001.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00002.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00002.png new file mode 100644 index 0000000..b71b25b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00003.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00003.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00004.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00004.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00005.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00005.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00006.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00006.png new file mode 100644 index 0000000..58eac55 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00007.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00007.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00008.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00008.png new file mode 100644 index 0000000..732826a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00008.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00009.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00009.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00009.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00010.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00010.png new file mode 100644 index 0000000..4738c2b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00011.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00011.png new file mode 100644 index 0000000..d18d495 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00020.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00021.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00022.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00022.png new file mode 100644 index 0000000..b71b25b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00030.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00030.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00030.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00031.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00031.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00031.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00032.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00032.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00032.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00033.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00033.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00033.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00034.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00034.png new file mode 100644 index 0000000..58eac55 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00034.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00035.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00035.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00035.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00036.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00036.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00036.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00037.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00037.png new file mode 100644 index 0000000..1611a57 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00037.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00000.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00001.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00002.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00002.png new file mode 100644 index 0000000..62b7685 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00003.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00003.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00004.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00004.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00005.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00005.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00006.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00006.png new file mode 100644 index 0000000..6cf46ea Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00007.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00007.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00008.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00008.png new file mode 100644 index 0000000..b0aa4e8 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00008.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00009.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00009.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00009.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00010.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00010.png new file mode 100644 index 0000000..a6a6827 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00011.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00011.png new file mode 100644 index 0000000..315c395 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00012.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00012.png new file mode 100644 index 0000000..f766f97 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00020.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00021.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00022.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00022.png new file mode 100644 index 0000000..62b7685 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00030.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00030.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00030.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00031.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00031.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00031.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00032.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00032.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00032.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00033.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00033.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00033.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00034.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00034.png new file mode 100644 index 0000000..6cf46ea Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00034.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00035.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00035.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00035.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00036.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00036.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00036.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_order_fill/00037.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00037.png new file mode 100644 index 0000000..6e341c1 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_order_fill/00037.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_refused/00000.png b/tests/snapshots/nanosp/test_sign_tx_refused/00000.png new file mode 100644 index 0000000..1597f7e Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_refused/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_refused/00001.png b/tests/snapshots/nanosp/test_sign_tx_refused/00001.png new file mode 100644 index 0000000..8a3938b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_refused/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_refused/00002.png b/tests/snapshots/nanosp/test_sign_tx_refused/00002.png new file mode 100644 index 0000000..8b3c9da Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_refused/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_refused/00003.png b/tests/snapshots/nanosp/test_sign_tx_refused/00003.png new file mode 100644 index 0000000..4a2929d Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_refused/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_refused/00004.png b/tests/snapshots/nanosp/test_sign_tx_refused/00004.png new file mode 100644 index 0000000..09a1af1 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_refused/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_refused/00005.png b/tests/snapshots/nanosp/test_sign_tx_refused/00005.png new file mode 100644 index 0000000..26c6197 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_refused/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx/00000.png b/tests/snapshots/nanosp/test_sign_tx_short_tx/00000.png new file mode 100644 index 0000000..030b884 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx/00001.png b/tests/snapshots/nanosp/test_sign_tx_short_tx/00001.png new file mode 100644 index 0000000..192c2bd Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx/00002.png b/tests/snapshots/nanosp/test_sign_tx_short_tx/00002.png new file mode 100644 index 0000000..75337cb Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx/00003.png b/tests/snapshots/nanosp/test_sign_tx_short_tx/00003.png new file mode 100644 index 0000000..57832de Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx/00004.png b/tests/snapshots/nanosp/test_sign_tx_short_tx/00004.png new file mode 100644 index 0000000..7389ab6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx/00005.png b/tests/snapshots/nanosp/test_sign_tx_short_tx/00005.png new file mode 100644 index 0000000..32e7443 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx/00006.png b/tests/snapshots/nanosp/test_sign_tx_short_tx/00006.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00000.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00001.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00001.png new file mode 100644 index 0000000..75337cb Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00002.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00002.png new file mode 100644 index 0000000..0378fc6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00003.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00003.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00004.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00004.png new file mode 100644 index 0000000..639af51 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00005.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00005.png new file mode 100644 index 0000000..7898c99 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00006.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00006.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00010.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00010.png new file mode 100644 index 0000000..e2e6efc Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00011.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00011.png new file mode 100644 index 0000000..75337cb Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00012.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00012.png new file mode 100644 index 0000000..0378fc6 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00012.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00013.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00013.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00013.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00014.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00014.png new file mode 100644 index 0000000..639af51 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00014.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00015.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00015.png new file mode 100644 index 0000000..7898c99 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_transfer/00015.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00000.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00001.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00002.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00002.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00003.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00003.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00004.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00004.png new file mode 100644 index 0000000..fb41633 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00005.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00005.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00006.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00006.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00010.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00010.png new file mode 100644 index 0000000..6336f24 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00011.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00011.png new file mode 100644 index 0000000..1853ea2 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00020.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00021.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00022.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00022.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00023.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00023.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00024.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00024.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00024.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00025.png b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00025.png new file mode 100644 index 0000000..ddae9bc Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unfreeze_tokens/00025.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00000.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00001.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00002.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00002.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00003.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00003.png new file mode 100644 index 0000000..8973d80 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00004.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00004.png new file mode 100644 index 0000000..8ed052d Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00004.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00005.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00005.png new file mode 100644 index 0000000..fce7d0b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00006.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00006.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00007.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00007.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00007.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00010.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00010.png new file mode 100644 index 0000000..57c605e Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00010.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00011.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00011.png new file mode 100644 index 0000000..129fb85 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00011.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00020.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00020.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00021.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00021.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00022.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00022.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00022.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00023.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00023.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00024.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00024.png new file mode 100644 index 0000000..8973d80 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00024.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00025.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00025.png new file mode 100644 index 0000000..8ed052d Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00025.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00026.png b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00026.png new file mode 100644 index 0000000..39ef4a2 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_unmint_tokens/00026.png differ diff --git a/tests/snapshots/nanox/test_app_mainmenu/00000.png b/tests/snapshots/nanox/test_app_mainmenu/00000.png new file mode 100644 index 0000000..4073303 Binary files /dev/null and b/tests/snapshots/nanox/test_app_mainmenu/00000.png differ diff --git a/tests/snapshots/nanox/test_app_mainmenu/00001.png b/tests/snapshots/nanox/test_app_mainmenu/00001.png new file mode 100644 index 0000000..77bcafd Binary files /dev/null and b/tests/snapshots/nanox/test_app_mainmenu/00001.png differ diff --git a/tests/snapshots/nanox/test_app_mainmenu/00002.png b/tests/snapshots/nanox/test_app_mainmenu/00002.png new file mode 100644 index 0000000..f265d69 Binary files /dev/null and b/tests/snapshots/nanox/test_app_mainmenu/00002.png differ diff --git a/tests/snapshots/nanox/test_app_mainmenu/00003.png b/tests/snapshots/nanox/test_app_mainmenu/00003.png new file mode 100644 index 0000000..f265d69 Binary files /dev/null and b/tests/snapshots/nanox/test_app_mainmenu/00003.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00000.png b/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00000.png new file mode 100644 index 0000000..e2ead08 Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00000.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00001.png b/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00001.png new file mode 100644 index 0000000..602c22a Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00001.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00002.png b/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00002.png new file mode 100644 index 0000000..305308f Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00002.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00003.png b/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00003.png new file mode 100644 index 0000000..7dfa0c5 Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00003.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00004.png b/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00004.png new file mode 100644 index 0000000..84caa59 Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_accepted/00004.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_refused/00000.png b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00000.png new file mode 100644 index 0000000..e2ead08 Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00000.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_refused/00001.png b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00001.png new file mode 100644 index 0000000..602c22a Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00001.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_refused/00002.png b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00002.png new file mode 100644 index 0000000..305308f Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00002.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_refused/00003.png b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00003.png new file mode 100644 index 0000000..7dfa0c5 Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00003.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_refused/00004.png b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00004.png new file mode 100644 index 0000000..7b38f99 Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00004.png differ diff --git a/tests/snapshots/nanox/test_get_public_key_confirm_refused/00005.png b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00005.png new file mode 100644 index 0000000..03e5ee2 Binary files /dev/null and b/tests/snapshots/nanox/test_get_public_key_confirm_refused/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_message/00000.png b/tests/snapshots/nanox/test_sign_message/00000.png new file mode 100644 index 0000000..2e4d511 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_message/00001.png b/tests/snapshots/nanox/test_sign_message/00001.png new file mode 100644 index 0000000..8cae4d6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_message/00002.png b/tests/snapshots/nanox/test_sign_message/00002.png new file mode 100644 index 0000000..602c22a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_message/00003.png b/tests/snapshots/nanox/test_sign_message/00003.png new file mode 100644 index 0000000..305308f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_message/00004.png b/tests/snapshots/nanox/test_sign_message/00004.png new file mode 100644 index 0000000..3617b8d Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_message/00005.png b/tests/snapshots/nanox/test_sign_message/00005.png new file mode 100644 index 0000000..55bb5c8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_message/00006.png b/tests/snapshots/nanox/test_sign_message/00006.png new file mode 100644 index 0000000..ab20bae Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_message_pkh/00000.png b/tests/snapshots/nanox/test_sign_message_pkh/00000.png new file mode 100644 index 0000000..2e4d511 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_pkh/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_message_pkh/00001.png b/tests/snapshots/nanox/test_sign_message_pkh/00001.png new file mode 100644 index 0000000..8cae4d6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_pkh/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_message_pkh/00002.png b/tests/snapshots/nanox/test_sign_message_pkh/00002.png new file mode 100644 index 0000000..208f5d8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_pkh/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_message_pkh/00003.png b/tests/snapshots/nanox/test_sign_message_pkh/00003.png new file mode 100644 index 0000000..3617b8d Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_pkh/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_message_pkh/00004.png b/tests/snapshots/nanox/test_sign_message_pkh/00004.png new file mode 100644 index 0000000..55bb5c8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_pkh/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_message_pkh/00005.png b/tests/snapshots/nanox/test_sign_message_pkh/00005.png new file mode 100644 index 0000000..ab20bae Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_pkh/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_message_refused/00000.png b/tests/snapshots/nanox/test_sign_message_refused/00000.png new file mode 100644 index 0000000..2e4d511 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_refused/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_message_refused/00001.png b/tests/snapshots/nanox/test_sign_message_refused/00001.png new file mode 100644 index 0000000..8cae4d6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_refused/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_message_refused/00002.png b/tests/snapshots/nanox/test_sign_message_refused/00002.png new file mode 100644 index 0000000..602c22a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_refused/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_message_refused/00003.png b/tests/snapshots/nanox/test_sign_message_refused/00003.png new file mode 100644 index 0000000..305308f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_refused/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_message_refused/00004.png b/tests/snapshots/nanox/test_sign_message_refused/00004.png new file mode 100644 index 0000000..3617b8d Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_refused/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_message_refused/00005.png b/tests/snapshots/nanox/test_sign_message_refused/00005.png new file mode 100644 index 0000000..55bb5c8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_refused/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_message_refused/00006.png b/tests/snapshots/nanox/test_sign_message_refused/00006.png new file mode 100644 index 0000000..12caa58 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_refused/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_message_refused/00007.png b/tests/snapshots/nanox/test_sign_message_refused/00007.png new file mode 100644 index 0000000..d917d19 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_message_refused/00007.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00000.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00001.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00002.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00002.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00003.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00003.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00004.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00004.png new file mode 100644 index 0000000..2fca943 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00005.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00005.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00010.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00010.png new file mode 100644 index 0000000..c408134 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00011.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00011.png new file mode 100644 index 0000000..fc6fca6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00012.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00012.png new file mode 100644 index 0000000..e2577f8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00013.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00013.png new file mode 100644 index 0000000..aa75038 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00013.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00020.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00021.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00022.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00022.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00023.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00023.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00024.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00024.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00024.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_authority/00025.png b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00025.png new file mode 100644 index 0000000..c81329e Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_authority/00025.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00000.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00001.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00002.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00002.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00003.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00003.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00004.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00004.png new file mode 100644 index 0000000..c7d5676 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00005.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00005.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00010.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00010.png new file mode 100644 index 0000000..de18f19 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00011.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00011.png new file mode 100644 index 0000000..39359b8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00012.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00012.png new file mode 100644 index 0000000..c335313 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00020.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00021.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00022.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00022.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00023.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00023.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00024.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00024.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00024.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00025.png b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00025.png new file mode 100644 index 0000000..d3f5cd6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_change_token_metadata_uri/00025.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00000.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00001.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00001.png new file mode 100644 index 0000000..2ce4f7e Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00002.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00002.png new file mode 100644 index 0000000..3169a43 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00003.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00003.png new file mode 100644 index 0000000..4100b0b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00004.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00004.png new file mode 100644 index 0000000..46b368c Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00005.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00005.png new file mode 100644 index 0000000..0f6ca54 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00006.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00006.png new file mode 100644 index 0000000..32a3fd1 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00007.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00007.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00007.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00010.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00010.png new file mode 100644 index 0000000..7c23f06 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00011.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00011.png new file mode 100644 index 0000000..59d0e80 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00012.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00012.png new file mode 100644 index 0000000..3d01046 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00013.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00013.png new file mode 100644 index 0000000..f62cce2 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00013.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00014.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00014.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00014.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00015.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00015.png new file mode 100644 index 0000000..0f6ca54 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00015.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_delegation/00016.png b/tests/snapshots/nanox/test_sign_tx_create_delegation/00016.png new file mode 100644 index 0000000..17cf916 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_delegation/00016.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00000.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00001.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00001.png new file mode 100644 index 0000000..3fbfcda Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00002.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00002.png new file mode 100644 index 0000000..dc3f263 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00003.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00003.png new file mode 100644 index 0000000..dd49ec2 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00004.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00004.png new file mode 100644 index 0000000..7623766 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00005.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00005.png new file mode 100644 index 0000000..0562b8b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00006.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00006.png new file mode 100644 index 0000000..9880fbf Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00007.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00007.png new file mode 100644 index 0000000..5d19c53 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00007.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00008.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00008.png new file mode 100644 index 0000000..7184c47 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00008.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00009.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00009.png new file mode 100644 index 0000000..f278bff Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00009.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00010.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00010.png new file mode 100644 index 0000000..139058c Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00011.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00011.png new file mode 100644 index 0000000..dc3f263 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00012.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00012.png new file mode 100644 index 0000000..dd49ec2 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00013.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00013.png new file mode 100644 index 0000000..7623766 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00013.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00014.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00014.png new file mode 100644 index 0000000..0562b8b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00014.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00015.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00015.png new file mode 100644 index 0000000..9880fbf Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00015.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00016.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00016.png new file mode 100644 index 0000000..5d19c53 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00016.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00017.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00017.png new file mode 100644 index 0000000..7184c47 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00017.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00018.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00018.png new file mode 100644 index 0000000..f278bff Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00018.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00019.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00019.png new file mode 100644 index 0000000..06704db Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00019.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00020.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00021.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00021.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00022.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00022.png new file mode 100644 index 0000000..b3afad9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00000.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00001.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00001.png new file mode 100644 index 0000000..3645243 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00002.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00002.png new file mode 100644 index 0000000..2df9d67 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00003.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00003.png new file mode 100644 index 0000000..0623b1b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00004.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00004.png new file mode 100644 index 0000000..bbd76c8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00005.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00005.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00010.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00010.png new file mode 100644 index 0000000..15001c0 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00011.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00011.png new file mode 100644 index 0000000..52979b5 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00012.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00012.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00013.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00013.png new file mode 100644 index 0000000..0623b1b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00013.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_delegation_staking/00014.png b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00014.png new file mode 100644 index 0000000..c6836c8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_delegation_staking/00014.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00000.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00001.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00002.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00002.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00003.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00003.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00004.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00004.png new file mode 100644 index 0000000..bc9b1a8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00005.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00005.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00010.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00010.png new file mode 100644 index 0000000..eaa64e5 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00011.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00011.png new file mode 100644 index 0000000..351a884 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00020.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00021.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00022.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00022.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00023.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00023.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00024.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00024.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00024.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00025.png b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00025.png new file mode 100644 index 0000000..567675f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_freeze_tokens/00025.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00000.png b/tests/snapshots/nanox/test_sign_tx_htlc/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00001.png b/tests/snapshots/nanox/test_sign_tx_htlc/00001.png new file mode 100644 index 0000000..aab0aed Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00002.png b/tests/snapshots/nanox/test_sign_tx_htlc/00002.png new file mode 100644 index 0000000..f113d41 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00003.png b/tests/snapshots/nanox/test_sign_tx_htlc/00003.png new file mode 100644 index 0000000..195e6f3 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00004.png b/tests/snapshots/nanox/test_sign_tx_htlc/00004.png new file mode 100644 index 0000000..778f66f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00005.png b/tests/snapshots/nanox/test_sign_tx_htlc/00005.png new file mode 100644 index 0000000..0d5d509 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00006.png b/tests/snapshots/nanox/test_sign_tx_htlc/00006.png new file mode 100644 index 0000000..5fc12d1 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00007.png b/tests/snapshots/nanox/test_sign_tx_htlc/00007.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00007.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00008.png b/tests/snapshots/nanox/test_sign_tx_htlc/00008.png new file mode 100644 index 0000000..62b7685 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00008.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00009.png b/tests/snapshots/nanox/test_sign_tx_htlc/00009.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00009.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00010.png b/tests/snapshots/nanox/test_sign_tx_htlc/00010.png new file mode 100644 index 0000000..40b1181 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00011.png b/tests/snapshots/nanox/test_sign_tx_htlc/00011.png new file mode 100644 index 0000000..f113d41 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00012.png b/tests/snapshots/nanox/test_sign_tx_htlc/00012.png new file mode 100644 index 0000000..195e6f3 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00013.png b/tests/snapshots/nanox/test_sign_tx_htlc/00013.png new file mode 100644 index 0000000..778f66f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00013.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00014.png b/tests/snapshots/nanox/test_sign_tx_htlc/00014.png new file mode 100644 index 0000000..0d5d509 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00014.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00015.png b/tests/snapshots/nanox/test_sign_tx_htlc/00015.png new file mode 100644 index 0000000..5fc12d1 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00015.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00020.png b/tests/snapshots/nanox/test_sign_tx_htlc/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00021.png b/tests/snapshots/nanox/test_sign_tx_htlc/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00022.png b/tests/snapshots/nanox/test_sign_tx_htlc/00022.png new file mode 100644 index 0000000..62b7685 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00023.png b/tests/snapshots/nanox/test_sign_tx_htlc/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00023.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00024.png b/tests/snapshots/nanox/test_sign_tx_htlc/00024.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00024.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_htlc/00025.png b/tests/snapshots/nanox/test_sign_tx_htlc/00025.png new file mode 100644 index 0000000..32f349e Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_htlc/00025.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00000.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00001.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00001.png new file mode 100644 index 0000000..00051f8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00002.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00002.png new file mode 100644 index 0000000..c09832c Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00003.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00003.png new file mode 100644 index 0000000..419f5f0 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00004.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00004.png new file mode 100644 index 0000000..26db145 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00005.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00005.png new file mode 100644 index 0000000..060d61b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00006.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00006.png new file mode 100644 index 0000000..0f6ca54 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00007.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00007.png new file mode 100644 index 0000000..d3ca23a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00007.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00008.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00008.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00008.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00010.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00010.png new file mode 100644 index 0000000..7c86f79 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00011.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00011.png new file mode 100644 index 0000000..7f8fb9a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00012.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00012.png new file mode 100644 index 0000000..7cd6829 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00013.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00013.png new file mode 100644 index 0000000..6d1bc9a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00013.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00014.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00014.png new file mode 100644 index 0000000..4c43c01 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00014.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00015.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00015.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00015.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00016.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00016.png new file mode 100644 index 0000000..0f6ca54 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00016.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00017.png b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00017.png new file mode 100644 index 0000000..caaaca0 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_fungible_token/00017.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00000.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00001.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00001.png new file mode 100644 index 0000000..2318573 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00002.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00002.png new file mode 100644 index 0000000..d84fdcd Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00003.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00003.png new file mode 100644 index 0000000..415b46b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00004.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00004.png new file mode 100644 index 0000000..7fb1f67 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00005.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00005.png new file mode 100644 index 0000000..e14acb6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00006.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00006.png new file mode 100644 index 0000000..03f61f6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00007.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00007.png new file mode 100644 index 0000000..f678edc Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00007.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00008.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00008.png new file mode 100644 index 0000000..0a262d5 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00008.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00009.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00009.png new file mode 100644 index 0000000..1a586fb Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00009.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00010.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00010.png new file mode 100644 index 0000000..84ff3f7 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00011.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00011.png new file mode 100644 index 0000000..3fdec7f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00012.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00012.png new file mode 100644 index 0000000..a9bd3e2 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00013.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00013.png new file mode 100644 index 0000000..b9a3aba Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00013.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00014.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00014.png new file mode 100644 index 0000000..b69697c Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00014.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00015.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00015.png new file mode 100644 index 0000000..651a3f4 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00015.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00016.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00016.png new file mode 100644 index 0000000..19e1140 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00016.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00017.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00017.png new file mode 100644 index 0000000..95bb380 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00017.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00018.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00018.png new file mode 100644 index 0000000..4cf446c Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00018.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00019.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00019.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00019.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00020.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00020.png new file mode 100644 index 0000000..af149c9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_issue_nft/00021.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00021.png new file mode 100644 index 0000000..8a6f6ed Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_issue_nft/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00000.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00001.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00001.png new file mode 100644 index 0000000..a7b61f1 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00002.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00002.png new file mode 100644 index 0000000..c31d61b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00003.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00003.png new file mode 100644 index 0000000..291da46 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00004.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00004.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00005.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00005.png new file mode 100644 index 0000000..62b8f91 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00006.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00006.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00010.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00010.png new file mode 100644 index 0000000..ac31f5f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00011.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00011.png new file mode 100644 index 0000000..b0f6c80 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00012.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00012.png new file mode 100644 index 0000000..eb0ade6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00020.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00021.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00021.png new file mode 100644 index 0000000..7a9b805 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00022.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00022.png new file mode 100644 index 0000000..342974f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00023.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00023.png new file mode 100644 index 0000000..a8a6913 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00023.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00024.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00024.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00024.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00025.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00025.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00025.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00026.png b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00026.png new file mode 100644 index 0000000..b00f750 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_lock_then_transfer/00026.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_long_tx/00000.png b/tests/snapshots/nanox/test_sign_tx_long_tx/00000.png new file mode 100644 index 0000000..1597f7e Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_long_tx/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_long_tx/00001.png b/tests/snapshots/nanox/test_sign_tx_long_tx/00001.png new file mode 100644 index 0000000..8a3938b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_long_tx/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_long_tx/00002.png b/tests/snapshots/nanox/test_sign_tx_long_tx/00002.png new file mode 100644 index 0000000..8b3c9da Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_long_tx/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_long_tx/00003.png b/tests/snapshots/nanox/test_sign_tx_long_tx/00003.png new file mode 100644 index 0000000..4a2929d Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_long_tx/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_long_tx/00004.png b/tests/snapshots/nanox/test_sign_tx_long_tx/00004.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_long_tx/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00000.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00001.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00001.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00002.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00002.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00003.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00003.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00004.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00004.png new file mode 100644 index 0000000..2b9bccd Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00005.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00005.png new file mode 100644 index 0000000..eeaad30 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00006.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00006.png new file mode 100644 index 0000000..b807f41 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00007.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00007.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00007.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00010.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00010.png new file mode 100644 index 0000000..05bd21a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00011.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00011.png new file mode 100644 index 0000000..50fb1e2 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00012.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00012.png new file mode 100644 index 0000000..51c42bd Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00020.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00021.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00021.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00022.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00022.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00023.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00023.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00023.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00024.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00024.png new file mode 100644 index 0000000..2b9bccd Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00024.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00025.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00025.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00025.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00026.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00026.png new file mode 100644 index 0000000..eeaad30 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00026.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_mint_tokens/00027.png b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00027.png new file mode 100644 index 0000000..f2eaa31 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_mint_tokens/00027.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00000.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00001.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00002.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00002.png new file mode 100644 index 0000000..b71b25b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00003.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00003.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00004.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00004.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00005.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00005.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00006.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00006.png new file mode 100644 index 0000000..58eac55 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00007.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00007.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00007.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00008.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00008.png new file mode 100644 index 0000000..732826a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00008.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00009.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00009.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00009.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00010.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00010.png new file mode 100644 index 0000000..4738c2b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00011.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00011.png new file mode 100644 index 0000000..d18d495 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00020.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00021.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00022.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00022.png new file mode 100644 index 0000000..b71b25b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00030.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00030.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00030.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00031.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00031.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00031.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00032.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00032.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00032.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00033.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00033.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00033.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00034.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00034.png new file mode 100644 index 0000000..58eac55 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00034.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00035.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00035.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00035.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00036.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00036.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00036.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_conclude/00037.png b/tests/snapshots/nanox/test_sign_tx_order_conclude/00037.png new file mode 100644 index 0000000..1611a57 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_conclude/00037.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00000.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00001.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00002.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00002.png new file mode 100644 index 0000000..62b7685 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00003.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00003.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00004.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00004.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00005.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00005.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00006.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00006.png new file mode 100644 index 0000000..6cf46ea Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00007.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00007.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00007.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00008.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00008.png new file mode 100644 index 0000000..b0aa4e8 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00008.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00009.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00009.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00009.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00010.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00010.png new file mode 100644 index 0000000..a6a6827 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00011.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00011.png new file mode 100644 index 0000000..315c395 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00012.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00012.png new file mode 100644 index 0000000..f766f97 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00020.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00021.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00022.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00022.png new file mode 100644 index 0000000..62b7685 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00030.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00030.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00030.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00031.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00031.png new file mode 100644 index 0000000..ec1e8cb Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00031.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00032.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00032.png new file mode 100644 index 0000000..5d5329a Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00032.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00033.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00033.png new file mode 100644 index 0000000..f12db18 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00033.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00034.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00034.png new file mode 100644 index 0000000..6cf46ea Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00034.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00035.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00035.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00035.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00036.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00036.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00036.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_order_fill/00037.png b/tests/snapshots/nanox/test_sign_tx_order_fill/00037.png new file mode 100644 index 0000000..6e341c1 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_order_fill/00037.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_refused/00000.png b/tests/snapshots/nanox/test_sign_tx_refused/00000.png new file mode 100644 index 0000000..1597f7e Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_refused/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_refused/00001.png b/tests/snapshots/nanox/test_sign_tx_refused/00001.png new file mode 100644 index 0000000..8a3938b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_refused/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_refused/00002.png b/tests/snapshots/nanox/test_sign_tx_refused/00002.png new file mode 100644 index 0000000..8b3c9da Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_refused/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_refused/00003.png b/tests/snapshots/nanox/test_sign_tx_refused/00003.png new file mode 100644 index 0000000..4a2929d Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_refused/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_refused/00004.png b/tests/snapshots/nanox/test_sign_tx_refused/00004.png new file mode 100644 index 0000000..09a1af1 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_refused/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_refused/00005.png b/tests/snapshots/nanox/test_sign_tx_refused/00005.png new file mode 100644 index 0000000..26c6197 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_refused/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_short_tx/00000.png b/tests/snapshots/nanox/test_sign_tx_short_tx/00000.png new file mode 100644 index 0000000..1597f7e Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_short_tx/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_short_tx/00001.png b/tests/snapshots/nanox/test_sign_tx_short_tx/00001.png new file mode 100644 index 0000000..ce243c5 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_short_tx/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_short_tx/00002.png b/tests/snapshots/nanox/test_sign_tx_short_tx/00002.png new file mode 100644 index 0000000..8b3c9da Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_short_tx/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_short_tx/00003.png b/tests/snapshots/nanox/test_sign_tx_short_tx/00003.png new file mode 100644 index 0000000..4a2929d Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_short_tx/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_short_tx/00004.png b/tests/snapshots/nanox/test_sign_tx_short_tx/00004.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_short_tx/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00000.png b/tests/snapshots/nanox/test_sign_tx_transfer/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00001.png b/tests/snapshots/nanox/test_sign_tx_transfer/00001.png new file mode 100644 index 0000000..192c2bd Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00002.png b/tests/snapshots/nanox/test_sign_tx_transfer/00002.png new file mode 100644 index 0000000..75337cb Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00003.png b/tests/snapshots/nanox/test_sign_tx_transfer/00003.png new file mode 100644 index 0000000..0378fc6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00004.png b/tests/snapshots/nanox/test_sign_tx_transfer/00004.png new file mode 100644 index 0000000..639af51 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00005.png b/tests/snapshots/nanox/test_sign_tx_transfer/00005.png new file mode 100644 index 0000000..6e3cb60 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00006.png b/tests/snapshots/nanox/test_sign_tx_transfer/00006.png new file mode 100644 index 0000000..3a16119 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00010.png b/tests/snapshots/nanox/test_sign_tx_transfer/00010.png new file mode 100644 index 0000000..e2e6efc Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00011.png b/tests/snapshots/nanox/test_sign_tx_transfer/00011.png new file mode 100644 index 0000000..75337cb Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00012.png b/tests/snapshots/nanox/test_sign_tx_transfer/00012.png new file mode 100644 index 0000000..0378fc6 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00012.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00013.png b/tests/snapshots/nanox/test_sign_tx_transfer/00013.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00013.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00014.png b/tests/snapshots/nanox/test_sign_tx_transfer/00014.png new file mode 100644 index 0000000..639af51 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00014.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_transfer/00015.png b/tests/snapshots/nanox/test_sign_tx_transfer/00015.png new file mode 100644 index 0000000..7898c99 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_transfer/00015.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00000.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00001.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00002.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00002.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00003.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00003.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00004.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00004.png new file mode 100644 index 0000000..fb41633 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00005.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00005.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00010.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00010.png new file mode 100644 index 0000000..6336f24 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00011.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00011.png new file mode 100644 index 0000000..1853ea2 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00020.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00021.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00022.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00022.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00023.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00023.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00024.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00024.png new file mode 100644 index 0000000..2737bf9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00024.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00025.png b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00025.png new file mode 100644 index 0000000..ddae9bc Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unfreeze_tokens/00025.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00000.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00000.png new file mode 100644 index 0000000..640e079 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00001.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00001.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00002.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00002.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00003.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00003.png new file mode 100644 index 0000000..8973d80 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00004.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00004.png new file mode 100644 index 0000000..8ed052d Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00005.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00005.png new file mode 100644 index 0000000..fce7d0b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00005.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00006.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00006.png new file mode 100644 index 0000000..b2e3594 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00006.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00010.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00010.png new file mode 100644 index 0000000..57c605e Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00010.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00011.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00011.png new file mode 100644 index 0000000..129fb85 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00011.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00020.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00020.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00020.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00021.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00021.png new file mode 100644 index 0000000..f8e1b29 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00021.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00022.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00022.png new file mode 100644 index 0000000..31b2df9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00022.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00023.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00023.png new file mode 100644 index 0000000..11e1d3f Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00023.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00024.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00024.png new file mode 100644 index 0000000..8973d80 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00024.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00025.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00025.png new file mode 100644 index 0000000..8ed052d Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00025.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00026.png b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00026.png new file mode 100644 index 0000000..39ef4a2 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_unmint_tokens/00026.png differ diff --git a/tests/snapshots/stax/test_app_mainmenu/00000.png b/tests/snapshots/stax/test_app_mainmenu/00000.png new file mode 100644 index 0000000..a08dbb1 Binary files /dev/null and b/tests/snapshots/stax/test_app_mainmenu/00000.png differ diff --git a/tests/snapshots/stax/test_app_mainmenu/00001.png b/tests/snapshots/stax/test_app_mainmenu/00001.png new file mode 100644 index 0000000..79a7cdf Binary files /dev/null and b/tests/snapshots/stax/test_app_mainmenu/00001.png differ diff --git a/tests/snapshots/stax/test_app_mainmenu/00002.png b/tests/snapshots/stax/test_app_mainmenu/00002.png new file mode 100644 index 0000000..b0c222a Binary files /dev/null and b/tests/snapshots/stax/test_app_mainmenu/00002.png differ diff --git a/tests/snapshots/stax/test_app_mainmenu/00003.png b/tests/snapshots/stax/test_app_mainmenu/00003.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_app_mainmenu/00003.png differ diff --git a/tests/snapshots/stax/test_get_public_key_confirm_accepted/00000.png b/tests/snapshots/stax/test_get_public_key_confirm_accepted/00000.png new file mode 100644 index 0000000..bbae86a Binary files /dev/null and b/tests/snapshots/stax/test_get_public_key_confirm_accepted/00000.png differ diff --git a/tests/snapshots/stax/test_get_public_key_confirm_accepted/00001.png b/tests/snapshots/stax/test_get_public_key_confirm_accepted/00001.png new file mode 100644 index 0000000..d3e68dd Binary files /dev/null and b/tests/snapshots/stax/test_get_public_key_confirm_accepted/00001.png differ diff --git a/tests/snapshots/stax/test_get_public_key_confirm_accepted/00002.png b/tests/snapshots/stax/test_get_public_key_confirm_accepted/00002.png new file mode 100644 index 0000000..ef04425 Binary files /dev/null and b/tests/snapshots/stax/test_get_public_key_confirm_accepted/00002.png differ diff --git a/tests/snapshots/stax/test_get_public_key_confirm_accepted/00003.png b/tests/snapshots/stax/test_get_public_key_confirm_accepted/00003.png new file mode 100644 index 0000000..a08dbb1 Binary files /dev/null and b/tests/snapshots/stax/test_get_public_key_confirm_accepted/00003.png differ diff --git a/tests/snapshots/stax/test_get_public_key_confirm_refused/00000.png b/tests/snapshots/stax/test_get_public_key_confirm_refused/00000.png new file mode 100644 index 0000000..bbae86a Binary files /dev/null and b/tests/snapshots/stax/test_get_public_key_confirm_refused/00000.png differ diff --git a/tests/snapshots/stax/test_get_public_key_confirm_refused/00001.png b/tests/snapshots/stax/test_get_public_key_confirm_refused/00001.png new file mode 100644 index 0000000..d3e68dd Binary files /dev/null and b/tests/snapshots/stax/test_get_public_key_confirm_refused/00001.png differ diff --git a/tests/snapshots/stax/test_get_public_key_confirm_refused/00002.png b/tests/snapshots/stax/test_get_public_key_confirm_refused/00002.png new file mode 100644 index 0000000..94c91bb Binary files /dev/null and b/tests/snapshots/stax/test_get_public_key_confirm_refused/00002.png differ diff --git a/tests/snapshots/stax/test_get_public_key_confirm_refused/00003.png b/tests/snapshots/stax/test_get_public_key_confirm_refused/00003.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_get_public_key_confirm_refused/00003.png differ diff --git a/tests/snapshots/stax/test_sign_message/00000.png b/tests/snapshots/stax/test_sign_message/00000.png new file mode 100644 index 0000000..5d5c468 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message/00000.png differ diff --git a/tests/snapshots/stax/test_sign_message/00001.png b/tests/snapshots/stax/test_sign_message/00001.png new file mode 100644 index 0000000..ede4fcc Binary files /dev/null and b/tests/snapshots/stax/test_sign_message/00001.png differ diff --git a/tests/snapshots/stax/test_sign_message/00002.png b/tests/snapshots/stax/test_sign_message/00002.png new file mode 100644 index 0000000..6b6fc92 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message/00002.png differ diff --git a/tests/snapshots/stax/test_sign_message/00003.png b/tests/snapshots/stax/test_sign_message/00003.png new file mode 100644 index 0000000..650a6f3 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message/00003.png differ diff --git a/tests/snapshots/stax/test_sign_message/00004.png b/tests/snapshots/stax/test_sign_message/00004.png new file mode 100644 index 0000000..a08dbb1 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message/00004.png differ diff --git a/tests/snapshots/stax/test_sign_message_pkh/00000.png b/tests/snapshots/stax/test_sign_message_pkh/00000.png new file mode 100644 index 0000000..5d5c468 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_pkh/00000.png differ diff --git a/tests/snapshots/stax/test_sign_message_pkh/00001.png b/tests/snapshots/stax/test_sign_message_pkh/00001.png new file mode 100644 index 0000000..bd48506 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_pkh/00001.png differ diff --git a/tests/snapshots/stax/test_sign_message_pkh/00002.png b/tests/snapshots/stax/test_sign_message_pkh/00002.png new file mode 100644 index 0000000..6b6fc92 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_pkh/00002.png differ diff --git a/tests/snapshots/stax/test_sign_message_pkh/00003.png b/tests/snapshots/stax/test_sign_message_pkh/00003.png new file mode 100644 index 0000000..650a6f3 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_pkh/00003.png differ diff --git a/tests/snapshots/stax/test_sign_message_pkh/00004.png b/tests/snapshots/stax/test_sign_message_pkh/00004.png new file mode 100644 index 0000000..a08dbb1 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_pkh/00004.png differ diff --git a/tests/snapshots/stax/test_sign_message_refused/00000.png b/tests/snapshots/stax/test_sign_message_refused/00000.png new file mode 100644 index 0000000..5d5c468 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_refused/00000.png differ diff --git a/tests/snapshots/stax/test_sign_message_refused/00001.png b/tests/snapshots/stax/test_sign_message_refused/00001.png new file mode 100644 index 0000000..ede4fcc Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_refused/00001.png differ diff --git a/tests/snapshots/stax/test_sign_message_refused/00002.png b/tests/snapshots/stax/test_sign_message_refused/00002.png new file mode 100644 index 0000000..6b6fc92 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_refused/00002.png differ diff --git a/tests/snapshots/stax/test_sign_message_refused/00003.png b/tests/snapshots/stax/test_sign_message_refused/00003.png new file mode 100644 index 0000000..45414d5 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_refused/00003.png differ diff --git a/tests/snapshots/stax/test_sign_message_refused/00004.png b/tests/snapshots/stax/test_sign_message_refused/00004.png new file mode 100644 index 0000000..fecace7 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_refused/00004.png differ diff --git a/tests/snapshots/stax/test_sign_message_refused/00005.png b/tests/snapshots/stax/test_sign_message_refused/00005.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_sign_message_refused/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00000.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00001.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00001.png new file mode 100644 index 0000000..013b703 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00002.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00002.png new file mode 100644 index 0000000..269b12a Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00003.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00003.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00004.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00004.png new file mode 100644 index 0000000..9e274be Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00010.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00010.png new file mode 100644 index 0000000..acda3e2 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00011.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00011.png new file mode 100644 index 0000000..acda3e2 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00020.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00020.png new file mode 100644 index 0000000..72d8de9 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00020.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00021.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00021.png new file mode 100644 index 0000000..33b0672 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00021.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00022.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00022.png new file mode 100644 index 0000000..9f62ac4 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00022.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_authority/00023.png b/tests/snapshots/stax/test_sign_tx_change_token_authority/00023.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_authority/00023.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00000.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00001.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00001.png new file mode 100644 index 0000000..013b703 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00002.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00002.png new file mode 100644 index 0000000..0d66aad Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00003.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00003.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00004.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00004.png new file mode 100644 index 0000000..9e274be Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00010.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00010.png new file mode 100644 index 0000000..eadaf06 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00011.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00011.png new file mode 100644 index 0000000..eadaf06 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00020.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00020.png new file mode 100644 index 0000000..72d8de9 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00020.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00021.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00021.png new file mode 100644 index 0000000..33b0672 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00021.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00022.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00022.png new file mode 100644 index 0000000..5154b60 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00022.png differ diff --git a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00023.png b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00023.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00023.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_delegation/00000.png b/tests/snapshots/stax/test_sign_tx_create_delegation/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_delegation/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_delegation/00001.png b/tests/snapshots/stax/test_sign_tx_create_delegation/00001.png new file mode 100644 index 0000000..d218625 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_delegation/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_delegation/00002.png b/tests/snapshots/stax/test_sign_tx_create_delegation/00002.png new file mode 100644 index 0000000..c009444 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_delegation/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_delegation/00003.png b/tests/snapshots/stax/test_sign_tx_create_delegation/00003.png new file mode 100644 index 0000000..3343c26 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_delegation/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_delegation/00004.png b/tests/snapshots/stax/test_sign_tx_create_delegation/00004.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_delegation/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_delegation/00005.png b/tests/snapshots/stax/test_sign_tx_create_delegation/00005.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_delegation/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_delegation/00010.png b/tests/snapshots/stax/test_sign_tx_create_delegation/00010.png new file mode 100644 index 0000000..8c29405 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_delegation/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_delegation/00011.png b/tests/snapshots/stax/test_sign_tx_create_delegation/00011.png new file mode 100644 index 0000000..1ba7dbc Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_delegation/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_delegation/00012.png b/tests/snapshots/stax/test_sign_tx_create_delegation/00012.png new file mode 100644 index 0000000..db55f1e Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_delegation/00012.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_delegation/00013.png b/tests/snapshots/stax/test_sign_tx_create_delegation/00013.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_delegation/00013.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00000.png b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00001.png b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00001.png new file mode 100644 index 0000000..608c3d6 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00002.png b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00002.png new file mode 100644 index 0000000..b1c1cd8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00003.png b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00003.png new file mode 100644 index 0000000..b91a1ee Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00004.png b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00004.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00005.png b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00005.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00010.png b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00010.png new file mode 100644 index 0000000..9481bf6 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00011.png b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00011.png new file mode 100644 index 0000000..33b0672 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00012.png b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00012.png new file mode 100644 index 0000000..c05cf3b Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00012.png differ diff --git a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00013.png b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00013.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_create_stake_pool/00013.png differ diff --git a/tests/snapshots/stax/test_sign_tx_delegation_staking/00000.png b/tests/snapshots/stax/test_sign_tx_delegation_staking/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_delegation_staking/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_delegation_staking/00001.png b/tests/snapshots/stax/test_sign_tx_delegation_staking/00001.png new file mode 100644 index 0000000..35ed6fc Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_delegation_staking/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_delegation_staking/00002.png b/tests/snapshots/stax/test_sign_tx_delegation_staking/00002.png new file mode 100644 index 0000000..c9c4a7d Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_delegation_staking/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_delegation_staking/00003.png b/tests/snapshots/stax/test_sign_tx_delegation_staking/00003.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_delegation_staking/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_delegation_staking/00004.png b/tests/snapshots/stax/test_sign_tx_delegation_staking/00004.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_delegation_staking/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_delegation_staking/00010.png b/tests/snapshots/stax/test_sign_tx_delegation_staking/00010.png new file mode 100644 index 0000000..1a066d1 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_delegation_staking/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_delegation_staking/00011.png b/tests/snapshots/stax/test_sign_tx_delegation_staking/00011.png new file mode 100644 index 0000000..171985a Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_delegation_staking/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_delegation_staking/00012.png b/tests/snapshots/stax/test_sign_tx_delegation_staking/00012.png new file mode 100644 index 0000000..6b5de9f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_delegation_staking/00012.png differ diff --git a/tests/snapshots/stax/test_sign_tx_delegation_staking/00013.png b/tests/snapshots/stax/test_sign_tx_delegation_staking/00013.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_delegation_staking/00013.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00000.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00001.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00001.png new file mode 100644 index 0000000..013b703 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00002.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00002.png new file mode 100644 index 0000000..d676523 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00003.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00003.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00004.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00004.png new file mode 100644 index 0000000..9e274be Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00010.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00010.png new file mode 100644 index 0000000..0923fc4 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00011.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00011.png new file mode 100644 index 0000000..0923fc4 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00020.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00020.png new file mode 100644 index 0000000..72d8de9 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00020.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00021.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00021.png new file mode 100644 index 0000000..33b0672 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00021.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00022.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00022.png new file mode 100644 index 0000000..c40ddea Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00022.png differ diff --git a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00023.png b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00023.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00023.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00000.png b/tests/snapshots/stax/test_sign_tx_htlc/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00001.png b/tests/snapshots/stax/test_sign_tx_htlc/00001.png new file mode 100644 index 0000000..6620584 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00002.png b/tests/snapshots/stax/test_sign_tx_htlc/00002.png new file mode 100644 index 0000000..bc6517b Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00003.png b/tests/snapshots/stax/test_sign_tx_htlc/00003.png new file mode 100644 index 0000000..4978a94 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00004.png b/tests/snapshots/stax/test_sign_tx_htlc/00004.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00005.png b/tests/snapshots/stax/test_sign_tx_htlc/00005.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00010.png b/tests/snapshots/stax/test_sign_tx_htlc/00010.png new file mode 100644 index 0000000..8572fd8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00011.png b/tests/snapshots/stax/test_sign_tx_htlc/00011.png new file mode 100644 index 0000000..8572fd8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00020.png b/tests/snapshots/stax/test_sign_tx_htlc/00020.png new file mode 100644 index 0000000..f6c837f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00020.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00021.png b/tests/snapshots/stax/test_sign_tx_htlc/00021.png new file mode 100644 index 0000000..33b0672 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00021.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00022.png b/tests/snapshots/stax/test_sign_tx_htlc/00022.png new file mode 100644 index 0000000..f316ee9 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00022.png differ diff --git a/tests/snapshots/stax/test_sign_tx_htlc/00023.png b/tests/snapshots/stax/test_sign_tx_htlc/00023.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_htlc/00023.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00000.png b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00001.png b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00001.png new file mode 100644 index 0000000..3db0e08 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00002.png b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00002.png new file mode 100644 index 0000000..c009444 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00003.png b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00003.png new file mode 100644 index 0000000..56b7625 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00004.png b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00004.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00005.png b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00005.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00010.png b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00010.png new file mode 100644 index 0000000..109b5f9 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00011.png b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00011.png new file mode 100644 index 0000000..1ba7dbc Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00012.png b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00012.png new file mode 100644 index 0000000..efce194 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00012.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00013.png b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00013.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00013.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_nft/00000.png b/tests/snapshots/stax/test_sign_tx_issue_nft/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_nft/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_nft/00001.png b/tests/snapshots/stax/test_sign_tx_issue_nft/00001.png new file mode 100644 index 0000000..f230c4a Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_nft/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_nft/00002.png b/tests/snapshots/stax/test_sign_tx_issue_nft/00002.png new file mode 100644 index 0000000..51f50f2 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_nft/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_nft/00003.png b/tests/snapshots/stax/test_sign_tx_issue_nft/00003.png new file mode 100644 index 0000000..f6bc246 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_nft/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_nft/00004.png b/tests/snapshots/stax/test_sign_tx_issue_nft/00004.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_nft/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_nft/00005.png b/tests/snapshots/stax/test_sign_tx_issue_nft/00005.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_nft/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_nft/00010.png b/tests/snapshots/stax/test_sign_tx_issue_nft/00010.png new file mode 100644 index 0000000..20c3f49 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_nft/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_nft/00011.png b/tests/snapshots/stax/test_sign_tx_issue_nft/00011.png new file mode 100644 index 0000000..82af017 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_nft/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_nft/00012.png b/tests/snapshots/stax/test_sign_tx_issue_nft/00012.png new file mode 100644 index 0000000..63885c4 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_nft/00012.png differ diff --git a/tests/snapshots/stax/test_sign_tx_issue_nft/00013.png b/tests/snapshots/stax/test_sign_tx_issue_nft/00013.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_issue_nft/00013.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00000.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00001.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00001.png new file mode 100644 index 0000000..fd9ba80 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00002.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00002.png new file mode 100644 index 0000000..b1c1cd8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00003.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00003.png new file mode 100644 index 0000000..f541d00 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00004.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00004.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00005.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00005.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00010.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00010.png new file mode 100644 index 0000000..9f3c01a Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00011.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00011.png new file mode 100644 index 0000000..9f3c01a Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00020.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00020.png new file mode 100644 index 0000000..0a6eca3 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00020.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00021.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00021.png new file mode 100644 index 0000000..33b0672 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00021.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00022.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00022.png new file mode 100644 index 0000000..9794da4 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00022.png differ diff --git a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00023.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00023.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00023.png differ diff --git a/tests/snapshots/stax/test_sign_tx_long_tx/00000.png b/tests/snapshots/stax/test_sign_tx_long_tx/00000.png new file mode 100644 index 0000000..46a27b1 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_long_tx/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_long_tx/00001.png b/tests/snapshots/stax/test_sign_tx_long_tx/00001.png new file mode 100644 index 0000000..71804d2 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_long_tx/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_long_tx/00002.png b/tests/snapshots/stax/test_sign_tx_long_tx/00002.png new file mode 100644 index 0000000..19e831c Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_long_tx/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_long_tx/00003.png b/tests/snapshots/stax/test_sign_tx_long_tx/00003.png new file mode 100644 index 0000000..f5e027f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_long_tx/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_long_tx/00004.png b/tests/snapshots/stax/test_sign_tx_long_tx/00004.png new file mode 100644 index 0000000..392165d Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_long_tx/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_long_tx/00005.png b/tests/snapshots/stax/test_sign_tx_long_tx/00005.png new file mode 100644 index 0000000..52f987c Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_long_tx/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00000.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00001.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00001.png new file mode 100644 index 0000000..71d44cc Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00002.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00002.png new file mode 100644 index 0000000..835929b Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00003.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00003.png new file mode 100644 index 0000000..12f0520 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00004.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00004.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00005.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00005.png new file mode 100644 index 0000000..9e274be Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00010.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00010.png new file mode 100644 index 0000000..97f7cab Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00011.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00011.png new file mode 100644 index 0000000..97f7cab Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00020.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00020.png new file mode 100644 index 0000000..963a02f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00020.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00021.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00021.png new file mode 100644 index 0000000..bf4012c Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00021.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00022.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00022.png new file mode 100644 index 0000000..6aa859c Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00022.png differ diff --git a/tests/snapshots/stax/test_sign_tx_mint_tokens/00023.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00023.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00023.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00000.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00001.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00001.png new file mode 100644 index 0000000..545c8fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00002.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00002.png new file mode 100644 index 0000000..538cefb Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00003.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00003.png new file mode 100644 index 0000000..034fc05 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00004.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00004.png new file mode 100644 index 0000000..596f1b1 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00005.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00005.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00006.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00006.png new file mode 100644 index 0000000..9e274be Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00006.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00010.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00010.png new file mode 100644 index 0000000..22942eb Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00011.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00011.png new file mode 100644 index 0000000..22942eb Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00020.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00020.png new file mode 100644 index 0000000..2dbab71 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00020.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00021.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00021.png new file mode 100644 index 0000000..2dbab71 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00021.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00030.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00030.png new file mode 100644 index 0000000..963a02f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00030.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00031.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00031.png new file mode 100644 index 0000000..33b0672 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00031.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00032.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00032.png new file mode 100644 index 0000000..49dbd18 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00032.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_conclude/00033.png b/tests/snapshots/stax/test_sign_tx_order_conclude/00033.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_conclude/00033.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00000.png b/tests/snapshots/stax/test_sign_tx_order_fill/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00001.png b/tests/snapshots/stax/test_sign_tx_order_fill/00001.png new file mode 100644 index 0000000..6789ed4 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00002.png b/tests/snapshots/stax/test_sign_tx_order_fill/00002.png new file mode 100644 index 0000000..538cefb Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00003.png b/tests/snapshots/stax/test_sign_tx_order_fill/00003.png new file mode 100644 index 0000000..034fc05 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00004.png b/tests/snapshots/stax/test_sign_tx_order_fill/00004.png new file mode 100644 index 0000000..1b588b9 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00005.png b/tests/snapshots/stax/test_sign_tx_order_fill/00005.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00006.png b/tests/snapshots/stax/test_sign_tx_order_fill/00006.png new file mode 100644 index 0000000..9e274be Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00006.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00010.png b/tests/snapshots/stax/test_sign_tx_order_fill/00010.png new file mode 100644 index 0000000..14b8012 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00011.png b/tests/snapshots/stax/test_sign_tx_order_fill/00011.png new file mode 100644 index 0000000..14b8012 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00020.png b/tests/snapshots/stax/test_sign_tx_order_fill/00020.png new file mode 100644 index 0000000..f6c837f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00020.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00021.png b/tests/snapshots/stax/test_sign_tx_order_fill/00021.png new file mode 100644 index 0000000..f6c837f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00021.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00030.png b/tests/snapshots/stax/test_sign_tx_order_fill/00030.png new file mode 100644 index 0000000..963a02f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00030.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00031.png b/tests/snapshots/stax/test_sign_tx_order_fill/00031.png new file mode 100644 index 0000000..33b0672 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00031.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00032.png b/tests/snapshots/stax/test_sign_tx_order_fill/00032.png new file mode 100644 index 0000000..6abc393 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00032.png differ diff --git a/tests/snapshots/stax/test_sign_tx_order_fill/00033.png b/tests/snapshots/stax/test_sign_tx_order_fill/00033.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_order_fill/00033.png differ diff --git a/tests/snapshots/stax/test_sign_tx_refused/00000.png b/tests/snapshots/stax/test_sign_tx_refused/00000.png new file mode 100644 index 0000000..7601f58 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_refused/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_refused/00001.png b/tests/snapshots/stax/test_sign_tx_refused/00001.png new file mode 100644 index 0000000..f2de498 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_refused/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_refused/00002.png b/tests/snapshots/stax/test_sign_tx_refused/00002.png new file mode 100644 index 0000000..bb50c81 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_refused/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_refused/00003.png b/tests/snapshots/stax/test_sign_tx_refused/00003.png new file mode 100644 index 0000000..abc9677 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_refused/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_refused/00004.png b/tests/snapshots/stax/test_sign_tx_refused/00004.png new file mode 100644 index 0000000..2b66970 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_refused/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_refused/00005.png b/tests/snapshots/stax/test_sign_tx_refused/00005.png new file mode 100644 index 0000000..52f987c Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_refused/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx/00000.png b/tests/snapshots/stax/test_sign_tx_short_tx/00000.png new file mode 100644 index 0000000..7601f58 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx/00001.png b/tests/snapshots/stax/test_sign_tx_short_tx/00001.png new file mode 100644 index 0000000..4168d43 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx/00002.png b/tests/snapshots/stax/test_sign_tx_short_tx/00002.png new file mode 100644 index 0000000..bb50c81 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx/00003.png b/tests/snapshots/stax/test_sign_tx_short_tx/00003.png new file mode 100644 index 0000000..392165d Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx/00004.png b/tests/snapshots/stax/test_sign_tx_short_tx/00004.png new file mode 100644 index 0000000..52f987c Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00000.png b/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00000.png new file mode 100644 index 0000000..7601f58 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00001.png b/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00001.png new file mode 100644 index 0000000..d658c95 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00002.png b/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00002.png new file mode 100644 index 0000000..bb50c81 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00003.png b/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00003.png new file mode 100644 index 0000000..392165d Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00004.png b/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00004.png new file mode 100644 index 0000000..52f987c Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_no_memo/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_transfer/00000.png b/tests/snapshots/stax/test_sign_tx_transfer/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_transfer/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_transfer/00001.png b/tests/snapshots/stax/test_sign_tx_transfer/00001.png new file mode 100644 index 0000000..edec633 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_transfer/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_transfer/00002.png b/tests/snapshots/stax/test_sign_tx_transfer/00002.png new file mode 100644 index 0000000..ea259ca Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_transfer/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_transfer/00003.png b/tests/snapshots/stax/test_sign_tx_transfer/00003.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_transfer/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_transfer/00004.png b/tests/snapshots/stax/test_sign_tx_transfer/00004.png new file mode 100644 index 0000000..d755792 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_transfer/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_transfer/00010.png b/tests/snapshots/stax/test_sign_tx_transfer/00010.png new file mode 100644 index 0000000..72f49ca Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_transfer/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_transfer/00011.png b/tests/snapshots/stax/test_sign_tx_transfer/00011.png new file mode 100644 index 0000000..7f25a0d Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_transfer/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_transfer/00012.png b/tests/snapshots/stax/test_sign_tx_transfer/00012.png new file mode 100644 index 0000000..fad9bf9 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_transfer/00012.png differ diff --git a/tests/snapshots/stax/test_sign_tx_transfer/00013.png b/tests/snapshots/stax/test_sign_tx_transfer/00013.png new file mode 100644 index 0000000..ceda6a8 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_transfer/00013.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00000.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00001.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00001.png new file mode 100644 index 0000000..013b703 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00002.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00002.png new file mode 100644 index 0000000..3dc1f34 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00003.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00003.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00004.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00004.png new file mode 100644 index 0000000..9e274be Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00010.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00010.png new file mode 100644 index 0000000..0ec4027 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00011.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00011.png new file mode 100644 index 0000000..0ec4027 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00020.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00020.png new file mode 100644 index 0000000..72d8de9 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00020.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00021.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00021.png new file mode 100644 index 0000000..33b0672 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00021.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00022.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00022.png new file mode 100644 index 0000000..a94fb9e Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00022.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00023.png b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00023.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00023.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00000.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00000.png new file mode 100644 index 0000000..a46449f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00001.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00001.png new file mode 100644 index 0000000..b33c474 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00002.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00002.png new file mode 100644 index 0000000..d71d1f4 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00003.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00003.png new file mode 100644 index 0000000..cb9e0d0 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00004.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00004.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00005.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00005.png new file mode 100644 index 0000000..9e274be Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00005.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00010.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00010.png new file mode 100644 index 0000000..5584da1 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00010.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00011.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00011.png new file mode 100644 index 0000000..5584da1 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00011.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00020.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00020.png new file mode 100644 index 0000000..72d8de9 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00020.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00021.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00021.png new file mode 100644 index 0000000..da9a826 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00021.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00022.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00022.png new file mode 100644 index 0000000..b6ae52c Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00022.png differ diff --git a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00023.png b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00023.png new file mode 100644 index 0000000..a5379fa Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00023.png differ diff --git a/tests/test_app_mainmenu.py b/tests/test_app_mainmenu.py new file mode 100644 index 0000000..a55bdc3 --- /dev/null +++ b/tests/test_app_mainmenu.py @@ -0,0 +1,19 @@ +from ragger.navigator import NavInsID + +from utils import ROOT_SCREENSHOT_PATH + + +# In this test we check the behavior of the device main menu +def test_app_mainmenu(device, navigator, test_name): + # Navigate in the main menu + if device.is_nano: + instructions = [ + NavInsID.RIGHT_CLICK, + NavInsID.RIGHT_CLICK + ] + else: + instructions = [ + NavInsID.USE_CASE_HOME_SETTINGS, + ] + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, test_name, instructions, + screen_change_before_first_instruction=False) diff --git a/tests/test_error_cmd.py b/tests/test_error_cmd.py new file mode 100644 index 0000000..f9d10a5 --- /dev/null +++ b/tests/test_error_cmd.py @@ -0,0 +1,227 @@ +import pytest +import scalecodec # type: ignore +from ragger.error import ExceptionRAPDU + +from application_client import MAINNET +from application_client.mintlayer_command_sender import (CLA, GetAppAndVersionP1, SignTxP1, P2, Errors, + InsType) + +tx_metadata_obj = scalecodec.base.RuntimeConfiguration().create_scale_object("TxMetadataReq") +sign_tx_req_obj = scalecodec.base.RuntimeConfiguration().create_scale_object("SignTxReq") + +# Ensure the app returns an error when a bad CLA is used +def test_bad_cla(backend): + with pytest.raises(ExceptionRAPDU) as e: + backend.exchange(cla=CLA + 1, ins=InsType.GET_PUBLIC_KEY) + assert e.value.status == Errors.SW_CLA_NOT_SUPPORTED + + +# Ensure the app returns an error when a bad INS is used +def test_bad_ins(backend): + with pytest.raises(ExceptionRAPDU) as e: + backend.exchange(cla=CLA, ins=0xFF) + assert e.value.status == Errors.SW_INS_NOT_SUPPORTED + + +# Ensure the app returns an error when a bad P1 or P2 is used +def test_wrong_p1p2(backend): + # Wrong P2 + with pytest.raises(ExceptionRAPDU) as e: + backend.exchange( + cla=CLA, ins=InsType.GET_PUBLIC_KEY, p1=GetAppAndVersionP1.P1_START, p2=123 + ) + assert e.value.status == Errors.SW_WRONG_P1P2 + + backend.exchange( + cla=CLA, ins=InsType.GET_PUBLIC_KEY, p1=GetAppAndVersionP1.P1_START, p2=P2.P2_MORE + ) + + # Wrong P1 after sending MORE + with pytest.raises(ExceptionRAPDU) as e: + backend.exchange( + cla=CLA, ins=InsType.GET_PUBLIC_KEY, p1=GetAppAndVersionP1.P1_START + 1, p2=P2.P2_MORE + ) + assert e.value.status == Errors.SW_WRONG_P1P2 + + +# Ensure the app returns an error when a bad data length is used +def test_wrong_data_length(backend): + # APDUs must be at least 4 bytes: CLA, INS, P1, P2. + with pytest.raises(ExceptionRAPDU) as e: + backend.exchange_raw(bytes.fromhex("E00300")) + assert e.value.status == Errors.SW_WRONG_APDU_LENGTH + # APDUs advertises a too long length + with pytest.raises(ExceptionRAPDU) as e: + backend.exchange_raw(bytes.fromhex("E003000005")) + assert e.value.status == Errors.SW_WRONG_APDU_LENGTH + + +# Ensure there is no state confusion when trying wrong APDU sequences +def test_invalid_state(backend): + with pytest.raises(ExceptionRAPDU) as e: + backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, # Try to continue a flow instead of start a new one + p2=P2.P2_LAST, + ) + assert e.value.status == Errors.SW_WRONG_CONTEXT + + +def test_sign_tx_invalid_coin(backend, scenario_navigator, device, navigator): + invalid_coin = 255 + num_inputs = 1 + num_outputs = 1 + metadata = tx_metadata_obj.encode( + { + "coin": invalid_coin, + "version": { + "V1": { + "num_inputs": num_inputs, + "num_outputs": num_outputs, + }, + }, + } + ).data + + with pytest.raises(ExceptionRAPDU) as e: + res = backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_START, + p2=P2.P2_LAST, + data=bytes(metadata), + ) + + assert e.value.status == Errors.SW_DESERIALIZE_FAIL + + +def test_sign_tx_invalid_context(backend, scenario_navigator, device, navigator): + """ + After metadata try to pass an output instead of the input + expect an error for wrong context + """ + num_inputs = 2 + num_outputs = 2 + metadata = tx_metadata_obj.encode( + { + "coin": MAINNET, + "version": { + "V1": { + "num_inputs": num_inputs, + "num_outputs": num_outputs, + }, + }, + } + ).data + + res = backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_START, + p2=P2.P2_LAST, + data=bytes(metadata), + ) + + assert res.status == 0x9000 + + with pytest.raises(ExceptionRAPDU) as e: + res = backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, + p2=P2.P2_LAST, + data=sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"Coin": 10}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)}} + } + }, + ], + } + } + } + ).data, + ) + assert e.value.status == Errors.SW_WRONG_CONTEXT + + +def test_sign_tx_invalid_input(backend, scenario_navigator, device, navigator): + num_inputs = 2 + num_outputs = 2 + metadata = tx_metadata_obj.encode( + { + "coin": MAINNET, + "version": { + "V1": { + "num_inputs": num_inputs, + "num_outputs": num_outputs, + }, + }, + } + ).data + + res = backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_START, + p2=P2.P2_LAST, + data=bytes(metadata), + ) + + print("res, ", res.status) + assert res.status == 0x9000 + + with pytest.raises(ExceptionRAPDU) as e: + res = backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, + p2=P2.P2_LAST, + data=bytes([0] * 10), + ) + + assert e.value.status == Errors.SW_DESERIALIZE_FAIL + + +def test_sign_tx_too_large_data(backend, scenario_navigator, device, navigator): + num_inputs = 2 + num_outputs = 2 + metadata = tx_metadata_obj.encode( + { + "coin": MAINNET, + "version": { + "V1": { + "num_inputs": num_inputs, + "num_outputs": num_outputs, + }, + }, + } + ).data + + res = backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_START, + p2=P2.P2_LAST, + data=bytes(metadata), + ) + + assert res.status == 0x9000 + + with pytest.raises(ExceptionRAPDU) as e: + for _ in range(100): + res = backend.exchange( + cla=CLA, + ins=InsType.SIGN_TX, + p1=SignTxP1.P1_NEXT, + p2=P2.P2_MORE, + data=b"big_input_data", + ) + + assert e.value.status == Errors.SW_MAX_BUFFER_LEN_EXCEEDED diff --git a/tests/test_name_version.py b/tests/test_name_version.py new file mode 100644 index 0000000..f822470 --- /dev/null +++ b/tests/test_name_version.py @@ -0,0 +1,16 @@ +from application_client.mintlayer_command_sender import MintlayerCommandSender +from application_client.mintlayer_response_unpacker import \ + unpack_get_app_and_version_response + + +# Test a specific APDU asking BOLOS (and not the app) the name and version of the current app +def test_get_app_and_version(backend, backend_name): + # Use the app interface instead of raw interface + client = MintlayerCommandSender(backend) + # Send the special instruction to BOLOS + response = client.get_app_and_version() + # Use an helper to parse the response, assert the values + app_name, version = unpack_get_app_and_version_response(response.data) + print(app_name, version) + assert app_name == "Mintlayer" + assert version == "0.1.0" diff --git a/tests/test_pubkey_cmd.py b/tests/test_pubkey_cmd.py new file mode 100644 index 0000000..377aab8 --- /dev/null +++ b/tests/test_pubkey_cmd.py @@ -0,0 +1,79 @@ +import pytest +from ragger.bip import CurveChoice, calculate_public_key_and_chaincode +from ragger.error import ExceptionRAPDU + +from application_client import MAINNET, TESTNET +from application_client.mintlayer_command_sender import ( + Errors, MintlayerCommandSender) +from application_client.mintlayer_response_unpacker import \ + unpack_get_public_key_response + +MNEMONIC = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" + + +# In this test we check that the GET_PUBLIC_KEY works in non-confirmation mode +def test_get_public_key_no_confirm(backend): + for path in [ + "m/44'/19788'/0'/0/0", + "m/44'/19788'/0/0/0", + "m/44'/19788'/911'/0/0", + "m/44'/19788'/255/255/255", + "m/44'/19788'/2147483647/0/0/0/0/0/0/0", + ]: + client = MintlayerCommandSender(backend) + response = client.get_public_key(coin=MAINNET, path=path).data + _, public_key, _, _ = unpack_get_public_key_response(response) + + ref_public_key, _ = calculate_public_key_and_chaincode( + CurveChoice.Secp256k1, path=path, mnemonic=MNEMONIC + ) + assert public_key.hex() == ref_public_key + + +def test_get_public_key_no_confirm_testnet(backend): + for path in [ + "m/44'/1'/0'/0/0", + "m/44'/1'/0/0/0", + "m/44'/1'/911'/0/0", + "m/44'/1'/255/255/255", + "m/44'/1'/2147483647/0/0/0/0/0/0/0", + ]: + client = MintlayerCommandSender(backend) + response = client.get_public_key(coin=TESTNET, path=path).data + _, public_key, _, _ = unpack_get_public_key_response(response) + + ref_public_key, _ = calculate_public_key_and_chaincode( + CurveChoice.Secp256k1, path=path, mnemonic=MNEMONIC + ) + assert public_key.hex() == ref_public_key + + +# In this test we check that the GET_PUBLIC_KEY works in confirmation mode +def test_get_public_key_confirm_accepted(backend, scenario_navigator): + client = MintlayerCommandSender(backend) + path = "m/44'/19788'/0'/0/0" + + with client.get_public_key_with_confirmation(coin=MAINNET, path=path): + scenario_navigator.address_review_approve() + + response = client.get_async_response().data + _, public_key, _, _ = unpack_get_public_key_response(response) + + ref_public_key, _ = calculate_public_key_and_chaincode( + CurveChoice.Secp256k1, path=path, mnemonic=MNEMONIC + ) + assert public_key.hex() == ref_public_key + + +# In this test we check that the GET_PUBLIC_KEY in confirmation mode replies an error if the user refuses +def test_get_public_key_confirm_refused(backend, scenario_navigator): + client = MintlayerCommandSender(backend) + path = "m/44'/19788'/0'/0/0" + + with pytest.raises(ExceptionRAPDU) as e: + with client.get_public_key_with_confirmation(coin=MAINNET, path=path): + scenario_navigator.address_review_reject() + + # Assert that we have received a refusal + assert e.value.status == Errors.SW_DENY + assert len(e.value.data) == 0 diff --git a/tests/test_sign_cmd.py b/tests/test_sign_cmd.py new file mode 100644 index 0000000..5bf93c0 --- /dev/null +++ b/tests/test_sign_cmd.py @@ -0,0 +1,1650 @@ +import pytest +import scalecodec +from ragger.navigator import NavIns, NavInsID + +from application_client import MAINNET +from application_client.mintlayer_command_sender import ( + MintlayerCommandSender, + sign_tx_review, + ReviewTransaction, +) +from application_client.mintlayer_response_unpacker import unpack_get_public_key_response +from application_client.mintlayer_transaction import Transaction + +sign_tx_req_obj = scalecodec.base.RuntimeConfiguration().create_scale_object("SignTxReq") + +TX_RESPONSE_SIZE = 71 + + +def test_sign_tx_transfer(backend, scenario_navigator, device, navigator): + # Use the app interface instead of raw interface + client = MintlayerCommandSender(backend) + # The path used for this entire test + path: str = "m/44'/19788'/0'/0/0" + + # First we need to get the public key of the device in order to build the transaction + rapdu = client.get_public_key(coin=MAINNET, path=path) + _, public_key, _, _ = unpack_get_public_key_response(rapdu.data) + + print("pk", len(public_key)) + + h = 1 << 31 + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 10}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)} + } + } + }, + ], + } + } + inp = sign_tx_req_obj.encode( + { + "Input": + { + "addresses": [ + {"path": [44 + h, 19788 + h, 0 + h, 0, 0], "multisig_idx": None} + ], + "inp": { + "Utxo": [ + { + "id": {"Transaction": "0x{}".format(bytes([0] * 32).hex())}, + "index": 1, + }, + additional_info, + ] + } + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info + } + ).data + + output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"Coin": 10}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)}} + } + }, + ], + } + } + } + ).data + # Create the transaction that will be sent to the device for signing + transaction = Transaction( + coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=False, + review_custom_screen_text=r"Sign\stransfer" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_lock_then_transfer(backend, scenario_navigator, device, navigator): + # Use the app interface instead of raw interface + client = MintlayerCommandSender(backend) + # The path used for this entire test + path: str = "m/44'/19788'/0'/0/0" + + h = 1 << 31 + inp = sign_tx_req_obj.encode( + { + "Input": + { + "addresses": [ + {"path": [44 + h, 19788 + h, 0 + h, 0, 0], "multisig_idx": None} + ], + "inp": { + "Account": { + "nonce": 1, + "account": {"Delegation": [[0] * 32, 11]}, + } + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": {"None": None} + } + ).data + + output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "LockThenTransfer": [ + {"Coin": 10}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)}} + } + }, + {"UntilHeight": 10}, + ], + } + } + } + ).data + + # Create the transaction that will be sent to the device for signing + transaction = Transaction( + coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=True, + review_custom_screen_text=r"Sign\swithdrawal" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_create_delegation(backend, scenario_navigator, device, navigator): + # Use the app interface instead of raw interface + client = MintlayerCommandSender(backend) + h = 1 << 31 + + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 10}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)} + } + } + }, + ], + } + } + inp = sign_tx_req_obj.encode( + { + "Input": + { + "addresses": [ + {"path": [44 + h, 19788 + h, 0 + h, 0, 0], "multisig_idx": None} + ], + "inp": { + "Utxo": [ + { + "id": {"Transaction": "0x{}".format(bytes([0] * 32).hex())}, + "index": 1, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info + } + ).data + + output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "CreateDelegationId": [ + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)}} + } + }, + [0] * 32, + ], + } + } + } + ).data + + # Create the transaction that will be sent to the device for signing + transaction = Transaction( + coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=False, + review_custom_screen_text=r"Sign\screate" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_delegation_staking(backend, scenario_navigator, device, navigator): + # Use the app interface instead of raw interface + client = MintlayerCommandSender(backend) + h = 1 << 31 + + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 10}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)} + } + } + }, + ], + } + } + inp = sign_tx_req_obj.encode( + { + "Input": + { + "addresses": [ + {"path": [44 + h, 19788 + h, 0 + h, 0, 0], "multisig_idx": None} + ], + "inp": { + "Utxo": [ + { + "id": {"Transaction": "0x{}".format(bytes([0] * 32).hex())}, + "index": 1, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info + } + ).data + + output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "DelegateStaking": [5, [0] * 32], + } + } + } + ).data + + # Create the transaction that will be sent to the device for signing + transaction = Transaction( + coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=False, + review_custom_screen_text=r"Sign\sstake" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_create_stake_pool(backend, scenario_navigator, device, navigator): + # Use the app interface instead of raw interface + client = MintlayerCommandSender(backend) + h = 1 << 31 + + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 40001}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)} + } + } + }, + ], + } + } + inp = sign_tx_req_obj.encode( + { + "Input": + { + "addresses": [ + {"path": [44 + h, 19788 + h, 0 + h, 0, 0], "multisig_idx": None} + ], + "inp": { + "Utxo": [ + { + "id": {"Transaction": "0x{}".format(bytes([0] * 32).hex())}, + "index": 1, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info + } + ).data + + output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "CreateStakePool": [ + [0] * 32, + { + "value": 40000, + "staker": { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)} + } + } + }, + "vrf_public_key": {"key": {"Schnorrkel": {"key": bytes([0] * 32)}}}, + "decommission_key": { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)} + } + } + }, + "margin_ratio_per_thousand": 10, + "cost_per_block": 5, + }, + ], + } + } + } + ).data + # Create the transaction that will be sent to the device for signing + transaction = Transaction( + coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=False, + review_custom_screen_text=r"Sign\screate\sstake" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_issue_fungible_token(backend, scenario_navigator, device, navigator): + # Use the app interface instead of raw interface + client = MintlayerCommandSender(backend) + h = 1 << 31 + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 10}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)} + } + } + }, + ], + } + } + inp = sign_tx_req_obj.encode( + { + "Input": + { + "addresses": [ + {"path": [44 + h, 19788 + h, 0 + h, 0, 0], "multisig_idx": None} + ], + "inp": { + "Utxo": [ + { + "id": {"Transaction": "0x{}".format(bytes([0] * 32).hex())}, + "index": 1, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info + } + ).data + + output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "IssueFungibleToken": { + "V1": { + "token_ticker": b"MYTKN", + "number_of_decimals": 8, + "metadata_uri": b"https://my.token.uri", + "total_supply": {"Fixed": 1000000000}, + "authority": { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)} + } + } + }, + "is_freezable": {"Yes": None}, + } + }, + } + } + } + ).data + + # Create the transaction that will be sent to the device for signing + transaction = Transaction( + coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=False, + review_custom_screen_text=r"Sign\screate\stoken" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_issue_nft(backend, scenario_navigator, device, navigator): + # Use the app interface instead of raw interface + client = MintlayerCommandSender(backend) + h = 1 << 31 + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 2000}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)} + } + } + }, + ], + } + } + inp = sign_tx_req_obj.encode( + { + "Input": + { + "addresses": [ + {"path": [44 + h, 19788 + h, 0 + h, 0, 0], "multisig_idx": None} + ], + "inp": { + "Utxo": [ + { + "id": {"Transaction": "0x{}".format(bytes([0] * 32).hex())}, + "index": 1, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info + } + ).data + + # This is the new output for issuing an NFT. + # The structure is (TokenId, NftIssuance, Destination) + output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "IssueNft": [ + bytes([0] * 32), + { + "V0": { + "metadata": { + "creator": { + "public_key": { + "key": { + "Secp256k1Schnorr": { + "pubkey_data": bytes([0] * 33) + } + } + } + }, + "name": b"MyAwesomeNFT", + "description": b"FirstNFT", + "ticker": b"MNFT1", + "icon_uri": b"https://my.nft/icon.png", + "additional_metadata_uri": b"https://my.nft/meta.json", + "media_uri": b"https://my.nft/media.jpg", + "media_hash": bytes([0] * 32), + } + } + }, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([0] * 33)}} + } + }, + ], + } + } + } + ).data + + # Create the transaction that will be sent to the device for signing + transaction = Transaction( + coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=False, + review_custom_screen_text=r"Sign\screate\sNFT" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_mint_tokens(backend, scenario_navigator, device, navigator): + """ + Test signing a transaction with two inputs: + 1. A standard UTXO input. + 2. An AccountCommand input to mint new tokens. + And one output to transfer the newly minted tokens. + """ + client = MintlayerCommandSender(backend) + h = 1 << 31 + bip44_path = [44 + h, 19788 + h, 0 + h, 0, 0] + + # The utxo (the previous TxOutput that this UTXO input spends) + # This represents an output of 100 coins owned by our key + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 100}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ], + } + } + utxo_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "Utxo": [ + { + "id": {"Transaction": f"0x{bytes([1]*32).hex()}"}, + "index": 0, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info + } + ).data + + # This is the AccountCommand to mint 1000 units of a new token + account_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "AccountCommand": [ + 1, # AccountNonce + { + "MintTokens": [ + f"0x{bytes([0]*32).hex()}", # TokenId + 1000, # Amount to mint + ] + }, + ] + }, + } + } + ).data + + acc_inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": {"None": None} + } + ).data + + mint_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"TokenV1": [f"0x{bytes([0]*32).hex()}", 1000]}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + transaction = Transaction( + coin=MAINNET, + inputs=[utxo_input, account_input], + input_commitments=[inp_commitment, acc_inp_commitment], + outputs=[mint_output], + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=True, + review_custom_screen_text=r"Sign\smint\stokens" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_unmint_tokens(backend, scenario_navigator, device, navigator): + """ + Test signing a transaction with two inputs: + 1. A standard UTXO input to pay tx fees. + 2. An AccountCommand input to unmint new tokens. + 3. A standard UTXO input with tokens to unmint + And one output to transfer the newly minted tokens. + """ + client = MintlayerCommandSender(backend) + h = 1 << 31 + bip44_path = [44 + h, 19788 + h, 0 + h, 0, 0] + + # The additional data (the previous TxOutput that this UTXO input spends) + # This represents an output of 100 coins owned by our key + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 100}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ], + } + } + additional_info2 = { + "Utxo": { + "Transfer": [ + {"TokenV1": [f"0x{bytes([0]*32).hex()}", 1000]}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ], + } + } + utxo_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "Utxo": [ + { + "id": {"Transaction": f"0x{bytes([1]*32).hex()}"}, + "index": 0, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info, + } + ).data + + utxo_input2 = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "Utxo": [ + { + "id": {"Transaction": f"0x{bytes([1]*32).hex()}"}, + "index": 2, + }, + additional_info2, + ] + }, + } + } + ).data + + inp_commitment2 = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info2, + } + ).data + + account_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "AccountCommand": [ + 1, # AccountNonce + { + "UnmintTokens": f"0x{bytes([0]*32).hex()}", # TokenId + }, + ] + }, + } + } + ).data + + acc_inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": {"None": None} + } + ).data + + change_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"Coin": 99}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + transaction = Transaction( + coin=MAINNET, + inputs=[utxo_input, account_input, utxo_input2], + input_commitments=[inp_commitment, acc_inp_commitment, inp_commitment2], + outputs=[change_output], + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=True, + review_custom_screen_text=r"Sign\sunmint\stokens" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_freeze_tokens(backend, scenario_navigator, device, navigator): + """ + Test signing a transaction with two inputs: + 1. A standard UTXO input to pay for tx fees. + 2. An AccountCommand input to freeze the tokens. + And one output to transfer the change coins. + """ + client = MintlayerCommandSender(backend) + h = 1 << 31 + bip44_path = [44 + h, 19788 + h, 0 + h, 0, 0] + + # The additional info (the previous TxOutput that this UTXO input spends) + # This represents an output of 100 coins owned by our key + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 100}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ], + } + } + + utxo_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "Utxo": [ + { + "id": {"Transaction": f"0x{bytes([1]*32).hex()}"}, + "index": 0, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info, + } + ).data + + # This is the AccountCommand to mint 1000 units of a new token + account_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "AccountCommand": [ + 1, # AccountNonce + {"FreezeToken": [f"0x{bytes([0]*32).hex()}", {"No": None}]}, # TokenId + ] + }, + } + } + ).data + + acc_inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": {"None": None} + } + ).data + + change_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"Coin": 99}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + transaction = Transaction( + coin=MAINNET, + inputs=[utxo_input, account_input], + input_commitments=[inp_commitment, acc_inp_commitment], + outputs=[change_output], + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=True, + review_custom_screen_text=r"Sign\sfreeze\stokens" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_unfreeze_tokens(backend, scenario_navigator, device, navigator): + """ + Test signing a transaction with two inputs: + 1. A standard UTXO input to pay for tx fees. + 2. An AccountCommand input to unfreeze the tokens. + And one output to transfer the change coins. + """ + client = MintlayerCommandSender(backend) + h = 1 << 31 + bip44_path = [44 + h, 19788 + h, 0 + h, 0, 0] + + # The additional data (the previous TxOutput that this UTXO input spends) + # This represents an output of 100 coins owned by our key + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 100}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ], + } + } + utxo_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "Utxo": [ + { + "id": {"Transaction": f"0x{bytes([1]*32).hex()}"}, + "index": 0, + }, + additional_info, + ] + }, + } + }).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info, + } + ).data + + # This is the AccountCommand to mint 1000 units of a new token + account_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "AccountCommand": [ + 1, # AccountNonce + { + "UnfreezeToken": f"0x{bytes([0]*32).hex()}", # TokenId + }, + ] + }, + } + } + ).data + + acc_inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": {"None": None} + } + ).data + + change_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"Coin": 99}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + transaction = Transaction( + coin=MAINNET, + inputs=[utxo_input, account_input], + input_commitments=[inp_commitment, acc_inp_commitment], + outputs=[change_output], + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=True, + review_custom_screen_text=r"Sign\sunfreeze" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_change_token_authority(backend, scenario_navigator, device, navigator): + """ + Test signing a transaction with two inputs: + 1. A standard UTXO input to pay for tx fees. + 2. An AccountCommand input to change the token's authority. + And one output to transfer the change coins. + """ + client = MintlayerCommandSender(backend) + h = 1 << 31 + bip44_path = [44 + h, 19788 + h, 0 + h, 0, 0] + + # The additional data (the previous TxOutput that this UTXO input spends) + # This represents an output of 100 coins owned by our key + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 100}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ], + } + } + utxo_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "Utxo": [ + { + "id": {"Transaction": f"0x{bytes([1]*32).hex()}"}, + "index": 0, + }, + additional_info, + ] + }, + } + }).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info, + } + ).data + + # This is the AccountCommand to mint 1000 units of a new token + account_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "AccountCommand": [ + 1, # AccountNonce + { + "ChangeTokenAuthority": [ + f"0x{bytes([0]*32).hex()}", # TokenId + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ] + }, + ] + }, + } + } + ).data + + acc_inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": {"None": None} + } + ).data + + change_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"Coin": 99}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + transaction = Transaction( + coin=MAINNET, + inputs=[utxo_input, account_input], + input_commitments=[inp_commitment, acc_inp_commitment], + outputs=[change_output], + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=True, + review_custom_screen_text=r"Sign\schange\stoken" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_change_token_metadata_uri( + backend, scenario_navigator, device, navigator +): + """ + Test signing a transaction with two inputs: + 1. A standard UTXO input to pay for tx fees. + 2. An AccountCommand input to change the token's metadata uri. + And one output to transfer the change coins. + """ + client = MintlayerCommandSender(backend) + h = 1 << 31 + bip44_path = [44 + h, 19788 + h, 0 + h, 0, 0] + + # The additional info (the previous TxOutput that this UTXO input spends) + # This represents an output of 100 coins owned by our key + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 100}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ], + } + } + utxo_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "Utxo": [ + { + "id": {"Transaction": f"0x{bytes([1]*32).hex()}"}, + "index": 0, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info, + } + ).data + + # This is the AccountCommand to mint 1000 units of a new token + account_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "AccountCommand": [ + 1, # AccountNonce + { + "ChangeTokenMetadataUri": [ + f"0x{bytes([0]*32).hex()}", # TokenId + "uri.com".encode(), + ] + }, + ] + }, + } + } + ).data + + acc_inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": {"None": None} + } + ).data + + change_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"Coin": 99}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + transaction = Transaction( + coin=MAINNET, + inputs=[utxo_input, account_input], + input_commitments=[inp_commitment, acc_inp_commitment], + outputs=[change_output], + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=True, + review_custom_screen_text=r"Sign\schange\stoken" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_order_fill(backend, scenario_navigator, device, navigator): + """ + Test signing a transaction with two inputs: + 1. A standard UTXO input to pay for tx fees. + 2. An AccountCommand input to fill an order. + 3. A standard UTXO input to be used for the fill. + And one output to transfer the change coins. + """ + client = MintlayerCommandSender(backend) + h = 1 << 31 + bip44_path = [44 + h, 19788 + h, 0 + h, 0, 0] + + # The additionl info (the previous TxOutput that this UTXO input spends) + # This represents an output of 100 coins owned by our key + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 100}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ], + } + } + utxo_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "Utxo": [ + { + "id": {"Transaction": f"0x{bytes([1]*32).hex()}"}, + "index": 0, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info, + } + ).data + + fill_amount = 10 + fill_ask = 100 + fill_give = 1000 + + additional_order_info = { + "initially_asked": {"Coin": fill_ask}, + "initially_given": {"TokenV1": [f"0x{bytes([0]*32).hex()}", fill_give]}, + "ask_balance": 0, + "give_balance": 0, + } + # This is the OrderAccountCommand to fill 10 units + account_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "OrderAccountCommand": [ + { + "FillOrder": [ + f"0x{bytes([0]*32).hex()}", # OrderId + fill_amount, + ] + }, + additional_order_info, + ] + }, + } + } + ).data + + fill_order_inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": { + "FillOrderAccountCommand": [ + additional_order_info["initially_asked"], + additional_order_info["initially_given"], + ] + }, + } + ).data + + change_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"Coin": 100 - 1 - fill_amount}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + fill_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + { + "TokenV1": [ + f"0x{bytes([0]*32).hex()}", + fill_amount * fill_give // fill_ask, + ] + }, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + transaction = Transaction( + coin=MAINNET, + inputs=[utxo_input, account_input], + input_commitments=[inp_commitment, fill_order_inp_commitment], + outputs=[change_output, fill_output], + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=True, + review_custom_screen_text=r"Sign\sfill\sorder" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_order_conclude(backend, scenario_navigator, device, navigator): + """ + Test signing a transaction with two inputs: + 1. A standard UTXO input to pay for tx fees. + 2. An OrderAccountCommand input to conclude an order. + And one output to transfer the change coins + ask balance and another output for the give balance. + """ + client = MintlayerCommandSender(backend) + h = 1 << 31 + bip44_path = [44 + h, 19788 + h, 0 + h, 0, 0] + + # The additional_data (the previous TxOutput that this UTXO input spends) + # This represents an output of 100 coins owned by our key + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 100}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ], + } + } + utxo_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "Utxo": [ + { + "id": {"Transaction": f"0x{bytes([1]*32).hex()}"}, + "index": 0, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info, + } + ).data + + initial_ask = 100 + initial_give = 1000 + ask_balance = 10 + give_balance = 900 + + additional_order_info = { + "initially_asked": {"Coin": initial_ask}, + "initially_given": {"TokenV1": [f"0x{bytes([0]*32).hex()}", initial_give]}, + "ask_balance": ask_balance, + "give_balance": give_balance, + } + + # This is the OrderAccountCommand to fill 10 units + account_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "OrderAccountCommand": [ + { + "ConcludeOrder": f"0x{bytes([0]*32).hex()}", # OrderId + }, + additional_order_info, + ] + }, + } + } + ).data + + conclude_order_inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": { + "ConcludeOrderAccountCommand": [ + additional_order_info["initially_asked"], + additional_order_info["initially_given"], + additional_order_info["ask_balance"], + additional_order_info["give_balance"] + ] + }, + } + ).data + + change_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"Coin": 100 - 1 + ask_balance}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + conclude_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"TokenV1": [f"0x{bytes([0]*32).hex()}", give_balance]}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + transaction = Transaction( + coin=MAINNET, + inputs=[utxo_input, account_input], + input_commitments=[inp_commitment, conclude_order_inp_commitment], + outputs=[change_output, conclude_output], + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=True, + review_custom_screen_text=r"Sign\sconclude\sorder" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) + + +def test_sign_tx_htlc(backend, scenario_navigator, device, navigator): + """ + Test signing a transaction with one input: + 1. The standard UTXO input to pay for tx fees. + And one output to transfer the change coins and the HTLC output. + """ + client = MintlayerCommandSender(backend) + h = 1 << 31 + bip44_path = [44 + h, 19788 + h, 0 + h, 0, 0] + + # The additional info (the previous TxOutput that this UTXO input spends) + # This represents an output of 100 coins owned by our key + additional_info = { + "Utxo": { + "Transfer": [ + {"Coin": 100}, + { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + ], + } + } + utxo_input = sign_tx_req_obj.encode( + { + "Input": { + "addresses": [{"path": bip44_path, "multisig_idx": None}], + "inp": { + "Utxo": [ + { + "id": {"Transaction": f"0x{bytes([1]*32).hex()}"}, + "index": 0, + }, + additional_info, + ] + }, + } + } + ).data + + inp_commitment = sign_tx_req_obj.encode( + { + "InputCommitment": additional_info, + } + ).data + + change_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Transfer": [ + {"Coin": 89}, + { + "PublicKey": { + "key": {"Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)}} + } + }, + ], + } + } + } + ).data + + htlc_output = sign_tx_req_obj.encode( + { + "Output": { + "out": { + "Htlc": [ + {"Coin": 10}, + { + "secret_hash": [0] * 20, + "spend_key": { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([2] * 33)} + } + } + }, + "refund_timelock": {"UntilHeight": 100}, + "refund_key": { + "PublicKey": { + "key": { + "Secp256k1Schnorr": {"pubkey_data": bytes([3] * 33)} + } + } + }, + }, + ], + } + } + } + ).data + + transaction = Transaction( + coin=MAINNET, + inputs=[utxo_input], + input_commitments=[inp_commitment], + outputs=[htlc_output, change_output], + ) + + review_tx = ReviewTransaction( + transaction=transaction, + has_command_input=False, + review_custom_screen_text=r"Sign\screate\sHTLC" + ) + sign_tx_review(client, device, navigator, scenario_navigator, review_tx) diff --git a/tests/test_sign_message.py b/tests/test_sign_message.py new file mode 100644 index 0000000..16d8406 --- /dev/null +++ b/tests/test_sign_message.py @@ -0,0 +1,48 @@ +import pytest +from ragger.error import ExceptionRAPDU + +from application_client import MAINNET +from application_client.mintlayer_command_sender import ( + Errors, MintlayerCommandSender) +from application_client.mintlayer_response_unpacker import ( + unpack_sign_message_response, +) + + +# In this test we check that the message signing works +def test_sign_message(backend, scenario_navigator): + path = "m/44'/19788'/0'/0/0" + message = b"Hello" + client = MintlayerCommandSender(backend) + with client.sign_message(coin=MAINNET, addr_type=0, path=path, message=message): + scenario_navigator.review_approve() + + sig = unpack_sign_message_response(client.get_async_response().data) + assert len(sig) == 64 + +def test_sign_message_pkh(backend, scenario_navigator): + path = "m/44'/19788'/0'/0/0" + message = b"Hello" + client = MintlayerCommandSender(backend) + with client.sign_message(coin=MAINNET, addr_type=1, path=path, message=message): + scenario_navigator.review_approve() + + sig = unpack_sign_message_response(client.get_async_response().data) + assert len(sig) == 64 + + +# Message signing refused test +# The test will ask for a message signature that will be refused on screen +def test_sign_message_refused(backend, scenario_navigator): + # Use the app interface instead of raw interface + client = MintlayerCommandSender(backend) + path: str = "m/44'/19788'/0'/0/0" + message: bytes = b"Hello" + + with pytest.raises(ExceptionRAPDU) as e: + with client.sign_message(coin=MAINNET, addr_type=0, path=path, message=message): + scenario_navigator.review_reject() + + # Assert that we have received a refusal + assert e.value.status == Errors.SW_DENY + assert len(e.value.data) == 0 diff --git a/tests/usage.md b/tests/usage.md new file mode 100644 index 0000000..201d146 --- /dev/null +++ b/tests/usage.md @@ -0,0 +1,74 @@ +# How to use the Ragger test framework + +This framework allows testing the application on the Speculos emulator or on a real device using LedgerComm or LedgerWallet + + +## Quickly get started with Ragger and Speculos + +### Install ragger and dependencies + +``` +pip install --extra-index-url https://test.pypi.org/simple/ -r requirements.txt +sudo apt-get update && sudo apt-get install qemu-user-static +``` + +### Compile the application + +The application to test must be compiled for all required devices. +You can use for this the container `ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite`: +``` +docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest +cd # replace with the name of your app, (eg boilerplate) +docker run --user "$(id -u)":"$(id -g)" --rm -ti -v "$(realpath .):/app" --privileged -v "/dev/bus/usb:/dev/bus/usb" ledger-app-builder-lite:latest +make clean && make BOLOS_SDK=$_SDK # replace with one of [NANOS, NANOX, NANOSP, STAX, FLEX] +exit +``` + +### Run a simple test using the Speculos emulator + +You can use the following command to get your first experience with Ragger and Speculos +``` +pytest -v --tb=short --device nanox --display +``` +Or you can refer to the section `Available pytest options` to configure the options you want to use + + +### Run a simple test using a real device + +The application to test must be loaded and started on a Ledger device plugged in USB. +You can use for this the container `ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite`: +``` +docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest +cd app-/ # replace with the name of your app, (eg boilerplate) +docker run --user "$(id -u)":"$(id -g)" --rm -ti -v "$(realpath .):/app" --privileged -v "/dev/bus/usb:/dev/bus/usb" ledger-app-builder-lite:latest +make clean && make BOLOS_SDK=$_SDK load # replace with one of [NANOS, NANOX, NANOSP, STAX, FLEX] +exit +``` + +You can use the following command to get your first experience with Ragger and Ledgerwallet on a NANOX. +Make sure that the device is plugged, unlocked, and that the tested application is open. +``` +pytest -v --tb=short --device nanox --backend ledgerwallet +``` +Or you can refer to the section `Available pytest options` to configure the options you want to use + + +## Available pytest options + +Standard useful pytest options +``` + -v formats the test summary in a readable way + -s enable logs for successful tests, on Speculos it will enable app logs if compiled with DEBUG=1 + -k only run the tests that contain in their names + --tb=short in case of errors, formats the test traceback in a readable way +``` + +Custom pytest options +``` + --device run the test on the specified device [nanos,nanox,nanosp,stax,flex,all]. This parameter is mandatory + --backend run the tests against the backend [speculos, ledgercomm, ledgerwallet]. Speculos is the default + --display on Speculos, enables the display of the app screen using QT + --golden_run on Speculos, screen comparison functions will save the current screen instead of comparing + --log_apdu_file log all apdu exchanges to the file in parameter. The previous file content is erased +``` + diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..cb52233 --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,23 @@ +from pathlib import Path +from hashlib import sha256 +from sha3 import keccak_256 + +from ecdsa.curves import SECP256k1 +from ecdsa.keys import VerifyingKey +from ecdsa.util import sigdecode_der + + +ROOT_SCREENSHOT_PATH = Path(__file__).parent.resolve() + + +# Check if a signature of a given message is valid +def check_signature_validity(public_key: bytes, signature: bytes, message: bytes) -> bool: + pk: VerifyingKey = VerifyingKey.from_string( + public_key, + curve=SECP256k1, + hashfunc=sha256 + ) + return pk.verify(signature=signature, + data=message, + hashfunc=keccak_256, + sigdecode=sigdecode_der)