diff --git a/.cargo/config.toml b/.cargo/config.toml index cd2f521..010ec9d 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,9 +1,3 @@ -[target.apex_p] -runner = "speculos -m apex_p" - -[build] -target = "apex_p" - [profile.release] opt-level = 'z' lto = true 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/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 index 814b669..246e261 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ __pycache__/ ledger/ # Build directory build/ + +# VSCode +.vscode/ diff --git a/Cargo.lock b/Cargo.lock index f6331dd..4f1a245 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arbitrary" @@ -63,23 +63,23 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "av1-grain" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" dependencies = [ "anyhow", "arrayvec", "log", - "nom", + "nom 8.0.0", "num-rational", "v_frame", ] [[package]] name = "avif-serialize" -version = "0.8.6" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" dependencies = [ "arrayvec", ] @@ -112,9 +112,9 @@ dependencies = [ [[package]] name = "bit_field" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" [[package]] name = "bitflags" @@ -136,9 +136,9 @@ checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "byte-slice-cast" @@ -175,7 +175,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom", + "nom 7.1.3", ] [[package]] @@ -368,9 +368,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "exr" -version = "1.73.0" +version = "1.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" dependencies = [ "bit_field", "half", @@ -383,23 +383,9 @@ dependencies = [ [[package]] name = "fax" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" -dependencies = [ - "fax_derive", -] - -[[package]] -name = "fax_derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" [[package]] name = "fdeflate" @@ -431,25 +417,25 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.7+wasi-0.2.4", + "wasip2", ] [[package]] @@ -470,12 +456,13 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "zerocopy", ] [[package]] @@ -532,9 +519,9 @@ dependencies = [ [[package]] name = "imgref" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" +checksum = "40fac9d56ed6437b198fddba683305e8e2d651aa42647f00f5ae542e7f5c94a2" [[package]] name = "impl-trait-for-tuples" @@ -549,9 +536,9 @@ dependencies = [ [[package]] name = "include_gif" -version = "1.2.6" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4046578028f0249b76fb88acb6a0eac1f635bf9e2630ba5d0562831597ffc323" +checksum = "59152fb9707e856f65a10a25ba0b7141589bcf5cbe7f653fcda2875e45fc78f7" dependencies = [ "flate2", "image", @@ -600,21 +587,21 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "lebe" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "ledger_device_sdk" -version = "1.34.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adde0c75d115974c33db5e8e50dbf809d874d64ea970570cd6cc523ce009d6b" +checksum = "85fc7dea35e2d9d0a305fc9594539af5f510cd7c2d764f944542c4710731ae58" dependencies = [ "const-zero", "include_gif", @@ -628,9 +615,9 @@ dependencies = [ [[package]] name = "ledger_secure_sdk_sys" -version = "1.15.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f18ccb022d22741651f4a13bb417e2e5f4f2d68b832409b80bdc3726e76b1bd9" +checksum = "58d50b8764859daf1b5176c5aad8ccc989494c16b08fa266e22c7907e60956e9" dependencies = [ "bindgen", "cc", @@ -647,9 +634,9 @@ checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libfuzzer-sys" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" dependencies = [ "arbitrary", "cc", @@ -702,16 +689,6 @@ version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" -[[package]] -name = "messages" -version = "0.1.0" -dependencies = [ - "derive_more", - "mintlayer-core-primitives", - "num_enum", - "parity-scale-codec", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -731,15 +708,24 @@ dependencies = [ [[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", - "image", "ledger_device_sdk", "ledger_secure_sdk_sys", - "messages", "mintlayer-core-primitives", + "mintlayer-messages", + "testmacro", ] [[package]] @@ -753,6 +739,16 @@ dependencies = [ "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" @@ -779,6 +775,15 @@ dependencies = [ "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" @@ -864,9 +869,9 @@ checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f" [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "parity-scale-codec" @@ -900,9 +905,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "png" @@ -956,18 +961,18 @@ dependencies = [ [[package]] name = "profiling" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" dependencies = [ "profiling-procmacros", ] [[package]] name = "profiling-procmacros" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" dependencies = [ "quote", "syn 2.0.104", @@ -1014,9 +1019,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha", @@ -1039,7 +1044,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] @@ -1094,9 +1099,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -1104,9 +1109,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -1143,9 +1148,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rgb" -version = "0.8.52" +version = "0.8.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" [[package]] name = "rustc-hash" @@ -1320,6 +1325,16 @@ 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" @@ -1419,9 +1434,9 @@ dependencies = [ [[package]] name = "version-compare" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" [[package]] name = "wasi" @@ -1429,29 +1444,20 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasi" -version = "0.14.7+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" -dependencies = [ - "wasip2", -] - [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" dependencies = [ "cfg-if", "once_cell", @@ -1460,25 +1466,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.104", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1486,22 +1478,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn 2.0.104", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" dependencies = [ "unicode-ident", ] @@ -1594,24 +1586,24 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "bce33a6288fa3f072a8c2c7d0f2fdbb90e28298f0135c1f99b96c3db2efcc60b" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "8fd425244944f4ab65ccff928e7323354c5a018c75838362fdce749dfad2ee1e" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 2c026a3..6343154 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,28 +1,65 @@ [package] name = "mintlayer-app" -version = "0.1.0" +version.workspace = true edition = "2021" -[dependencies] -messages = { path = "./messages" } -ledger_device_sdk = "1.34.0" -ledger_secure_sdk_sys = "1.15.0" -hex = { version = "0.4.3", default-features = false, features = ["alloc"] } -bech32 = { version = "0.11", default-features = false, features = ["alloc"] } -chrono = { version = "0.4", default-features = false, features = ["alloc"] } - -[dependencies.mintlayer-core-primitives] +[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 = "0.25.8" +image.workspace = true -[features] -default = ["ledger_device_sdk/nano_nbgl"] -debug = ["ledger_device_sdk/debug"] +[[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"] @@ -44,8 +81,3 @@ icon = "icons/mintlayer_40x40.gif" [package.metadata.ledger.apex_p] icon = "icons/mintlayer_32x32.png" - -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = [ - 'cfg(target_os, values("apex_p", "stax", "flex", "nanos", "nanox", "nanosplus"))', -] } diff --git a/README.md b/README.md index dadff25..326d124 100644 --- a/README.md +++ b/README.md @@ -143,3 +143,7 @@ The following workflows are executed in [GitHub Actions](https://github.com/feat - 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 index 89a3680..25e883c 100644 --- a/build.rs +++ b/build.rs @@ -35,7 +35,7 @@ fn main() { .unwrap(); let output = Command::new("git") - .args(&["rev-parse", "HEAD"]) + .args(["rev-parse", "HEAD"]) .output() .expect("Failed to execute git command"); 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/src/app_ui/address.rs b/crates/app-core/src/app_ui/address.rs similarity index 95% rename from src/app_ui/address.rs rename to crates/app-core/src/app_ui/address.rs index 2d40bcd..daaa282 100644 --- a/src/app_ui/address.rs +++ b/crates/app-core/src/app_ui/address.rs @@ -20,7 +20,7 @@ use crate::{ app_ui::utils::{compress_public_key, load_glyph, to_address}, StatusWord, }; -use messages::mlcp::{CoinType, Destination, PublicKey}; +use mintlayer_messages::mlcp::{CoinType, Destination, PublicKey}; use ledger_device_sdk::{ ecc::ECPublicKey, diff --git a/src/app_ui/menu.rs b/crates/app-core/src/app_ui/menu.rs similarity index 84% rename from src/app_ui/menu.rs rename to crates/app-core/src/app_ui/menu.rs index 0521292..b6dff58 100644 --- a/src/app_ui/menu.rs +++ b/crates/app-core/src/app_ui/menu.rs @@ -24,11 +24,9 @@ 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"), - ) + NbglHomeAndSettings::new().glyph(&MINTLAYER).infos( + "Mintlayer", + env!("CARGO_PKG_VERSION"), + env!("CARGO_PKG_AUTHORS"), + ) } diff --git a/src/app_ui/sign.rs b/crates/app-core/src/app_ui/sign.rs similarity index 53% rename from src/app_ui/sign.rs rename to crates/app-core/src/app_ui/sign.rs index e5e5f1c..e12fe4a 100644 --- a/src/app_ui/sign.rs +++ b/crates/app-core/src/app_ui/sign.rs @@ -16,7 +16,6 @@ *****************************************************************************/ use alloc::string::String; -use alloc::vec::Vec; use alloc::{format, string::ToString}; use core::fmt::Write; @@ -24,13 +23,14 @@ use crate::{ app_ui::utils::{ bech32m_encode, compress_public_key, load_glyph, to_address, to_public_key_hash, }, - handlers::sign_tx::{CoinOrTokenId, TxContext, TxType}, + handlers::sign_tx::{CoinOrTokenId, InputCommand, TxParsingOutputsContext, TxType}, StatusWord, }; -use messages::{ +use mintlayer_messages::{ encode, mlcp::{ - Amount, CoinType, Destination, IsTokenFreezable, NftIssuance, OutputTimeLock, OutputValue, + AccountCommand, AccountSpending, Amount, CoinType, Destination, IsTokenFreezable, + IsTokenUnfreezable, NftIssuance, OrderAccountCommand, OutputTimeLock, OutputValue, PublicKey, TokenIssuance, TokenTotalSupply, TxOutput, VrfPublicKey, H256, }, AddrType, @@ -45,7 +45,12 @@ use ledger_device_sdk::{ }, }; -pub fn new_streaming_review() -> NbglStreamingReview { +struct FormatedOutput { + name: &'static str, + value: String, +} + +pub fn ui_new_streaming_review() -> NbglStreamingReview { const MINTLAYER: NbglGlyph = load_glyph(); NbglStreamingReview::new() @@ -53,19 +58,20 @@ pub fn new_streaming_review() -> NbglStreamingReview { .tx_type(TransactionType::Transaction) } -pub fn start_streaming_review(review: &NbglStreamingReview) -> bool { +pub fn ui_start_streaming_review(review: &NbglStreamingReview) -> bool { review.start("Review transaction", None) } -pub fn streaming_review_show_output( +pub fn ui_streaming_review_show_input( review: &NbglStreamingReview, - output: &TxOutput, + input: &InputCommand, coin: CoinType, ) -> Result { - let (name, value) = format_output(output, coin)?; + let input = format_input(input, coin)?; + let fields = [Field { - name, - value: &value, + name: input.name, + value: &input.value, }]; let res = match review.next(&fields) { @@ -76,15 +82,31 @@ pub fn streaming_review_show_output( Ok(res) } -pub fn approve_streaming_review( +pub fn ui_streaming_review_show_output( review: &NbglStreamingReview, output: &TxOutput, - ctx: &TxContext, + coin: CoinType, ) -> Result { - if !streaming_review_show_output(review, output, ctx.coin())? { - return Ok(false); - } + 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> { @@ -94,8 +116,8 @@ pub fn approve_streaming_review( CoinOrTokenId::Coin => writeln!( acc, "{} {}", - format_amount(Amount::from_atoms(fee), ctx.coin()), - ctx.coin().coin_ticker() + format_amount(Amount::from_atoms(fee), coin), + coin.coin_ticker() ) .map_err(|_| StatusWord::TxDisplayFail)?, @@ -104,7 +126,7 @@ pub fn approve_streaming_review( writeln!( acc, "{fee} {}", - id_to_address(token_id, ctx.coin().token_id_address_prefix())? + id_to_address(token_id, coin.token_id_address_prefix())? ) .map_err(|_| StatusWord::TxDisplayFail)? } @@ -125,102 +147,34 @@ pub fn approve_streaming_review( NbglStreamingReviewStatus::Next | NbglStreamingReviewStatus::Skipped => {} }; - let title = transaction_title(&ctx.tx_type()); + let title = transaction_title(&ctx.summary().tx_type()); Ok(review.finish(title)) } -/// Displays a transaction and returns true if user approved it. -/// -/// This method can return [`AppSW::TxDisplayFail`] error if the coin name length is too long. -/// -/// # Arguments -/// -/// * `ctx` - TxContext to be displayed for validation -pub fn ui_display_tx(ctx: &TxContext, outputs: &[TxOutput]) -> Result { - 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), ctx.coin()), - ctx.coin().coin_ticker() - ) - .map_err(|_| StatusWord::TxDisplayFail)?, - - CoinOrTokenId::TokenId(token_id) => { - if fee != 0 { - writeln!( - acc, - "{fee} {}", - id_to_address(token_id, ctx.coin().token_id_address_prefix())? - ) - .map_err(|_| StatusWord::TxDisplayFail)? - } - } - }; - - Ok(acc) - }, - )?; - - let formated_outputs: Vec<(&str, String)> = outputs - .iter() - .map(|out| format_output(out, ctx.coin())) - .collect::, _>>()?; - - // Define transaction review fields - let my_fields: Vec<_> = formated_outputs - .iter() - .map(|(name, value)| Field { name, value }) - .chain([Field { - name: "Fees:", - value: &fees, - }]) - .collect(); - - // Create transaction review - - const MINTLAYER: NbglGlyph = load_glyph(); - - let title = transaction_title(&ctx.tx_type()); - - // Create NBGL review. Maximum number of fields and string buffer length can be customised - // with constant generic parameters of NbglReview. Default values are 32 and 1024 respectively. - let review: NbglReview = NbglReview::new() - .titles("Review transaction", "", title) - .glyph(&MINTLAYER); - - Ok(review.show(&my_fields)) -} - 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::DelegationWithdrawl) => "Sign withdrawal Delegation transaction", + Some(TxType::CreateDelegation) => "Sign create delegation transaction", + Some(TxType::DelegationStake) => "Sign stake delegation transaction", + Some(TxType::DelegationWithdrawl) => "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::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", } } @@ -254,11 +208,11 @@ pub fn ui_display_message( let addr = to_address(&dest, coin_type)?; let message_str = match core::str::from_utf8(message) { - Ok(s) if s.bytes().all(|b| b >= 0x20 && b <= 0x7E) => s.to_string(), + Ok(s) if s.bytes().all(|b| (0x20..=0x7E).contains(&b)) => s.to_string(), Ok(_) | Err(_) => format!("0x{}", hex::encode(message)), }; - let my_fields = [ + let msg_fields = [ Field { name: "Address", value: addr.as_str(), @@ -282,7 +236,7 @@ pub fn ui_display_message( .glyph(&MINTLAYER); // Show the review screen with the defined fields and return the user's choice. - Ok(review.show(&my_fields)) + Ok(review.show(&msg_fields)) } fn vrf_to_address(key: &VrfPublicKey, coin: CoinType) -> Result { @@ -323,11 +277,11 @@ fn format_value(value: &OutputValue, coin: CoinType) -> Result Result { let seconds_i64: i64 = seconds_u64 .try_into() - .map_err(|_| StatusWord::TxDisplayFail)?; + .map_err(|_| StatusWord::TxLockTimeInvalid)?; let datetime = Utc .timestamp_opt(seconds_i64, 0) .earliest() - .ok_or(StatusWord::TxDisplayFail)?; + .ok_or(StatusWord::TxLockTimeInvalid)?; Ok(datetime.format("%Y-%m-%d %H:%M:%S").to_string()) } @@ -342,16 +296,16 @@ fn format_lock(lock: &OutputTimeLock) -> Result { Ok(s) } -/// Formats a transaction output into a tuple of (short_address, amount, address_label). +/// Formats a transaction output into a FormatedOutput. /// /// # Arguments /// * `output` - A reference to the `TxOutput` enum variant to format. -/// * `coin` - A reference to the coin information, used for formatting amounts. +/// * `coin` - The coin information, used for formatting amounts. /// /// # Returns -/// A tuple containing three `String`s: `(short_address, amount, address_label)`. -pub fn format_output(output: &TxOutput, coin: CoinType) -> Result<(&str, String), StatusWord> { - let res = match output { +/// 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!( @@ -368,10 +322,14 @@ pub fn format_output(output: &TxOutput, coin: CoinType) -> Result<(&str, String) format_lock(lock)?, format_value(value, coin)? ); - ("Lock then Transfer", address_short) + 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::Burn(value) => ("Burn", format_value(value, coin)?), TxOutput::CreateStakePool(pool_id, data) => { let address_short = format!( @@ -381,29 +339,50 @@ pub fn format_output(output: &TxOutput, coin: CoinType) -> Result<(&str, String) ("Create staking pool", address_short) } - TxOutput::ProduceBlockFromStake(destination, _pool_id) => ( - "Produce block from stake", - format!("New staker key: {}", to_address(destination, coin)?), - ), + 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())? ); - ("Create delegation", address_short) + + let name = if cfg!(any(target_os = "nanosplus", target_os = "nanox")) { + "Create deleg" + } else { + "Create delegation" + }; + + (name, address_short) } - TxOutput::DelegateStaking(amount, delegation_id) => ( - "Delegate staking", - format!( - "{}\n{}", - id_to_address(delegation_id.hash(), coin.delegation_id_address_prefix())?, - format_value(&OutputValue::Coin(*amount), coin)? - ), - ), + 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; @@ -427,15 +406,19 @@ pub fn format_output(output: &TxOutput, coin: CoinType) -> Result<(&str, String) "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 ); - ("Issue fungible token", address_short) + 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 data = match data { - NftIssuance::V0(data) => data, - }; + let NftIssuance::V0(data) = data; let address_short = format!( - "Name: {}\nCreator: {}\nTicker: {}\nAddress: {}\nIcon URI: {}\nAdditional medatada URI: {}\nMedia URI: {}", + "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()), @@ -444,7 +427,13 @@ pub fn format_output(output: &TxOutput, coin: CoinType) -> Result<(&str, String) String::from_utf8_lossy(data.additional_metadata_uri.as_ref()), String::from_utf8_lossy(data.media_uri.as_ref()) ); - ("Issue NFT token", address_short) + 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)), @@ -474,5 +463,132 @@ pub fn format_output(output: &TxOutput, coin: CoinType) -> Result<(&str, String) } }; - Ok(res) + 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 withdrawl", 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/src/app_ui/utils.rs b/crates/app-core/src/app_ui/utils.rs similarity index 89% rename from src/app_ui/utils.rs rename to crates/app-core/src/app_ui/utils.rs index 83f7e00..92a5200 100644 --- a/src/app_ui/utils.rs +++ b/crates/app-core/src/app_ui/utils.rs @@ -25,7 +25,7 @@ use ledger_device_sdk::{ }; use crate::StatusWord; -use messages::{ +use mintlayer_messages::{ encode, mlcp::{CoinType, Destination, PublicKeyHash, Secp256k1PublicKey}, }; @@ -48,13 +48,13 @@ pub fn to_address(destination: &Destination, coin: CoinType) -> Result NbglGlyph<'static> { #[cfg(target_os = "apex_p")] const MINTLAYER: NbglGlyph = - NbglGlyph::from_include(include_gif!("glyphs/mintlayer_48x48.png", NBGL)); + 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)); + 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)); + NbglGlyph::from_include(include_gif!("../../icons/mintlayer_14x14.gif", NBGL)); MINTLAYER } @@ -70,7 +70,7 @@ pub fn compress_public_key( let mut compressed_key = [0u8; 33]; let y_coordinate = &uncompressed_key[33..65]; - let prefix = if y_coordinate[31] % 2 == 0 { + let prefix = if y_coordinate[31].is_multiple_of(2) { 0x02 } else { 0x03 diff --git a/src/errors.rs b/crates/app-core/src/errors.rs similarity index 98% rename from src/errors.rs rename to crates/app-core/src/errors.rs index c7d13a2..84a5917 100644 --- a/src/errors.rs +++ b/crates/app-core/src/errors.rs @@ -16,7 +16,7 @@ *****************************************************************************/ use ledger_device_sdk::ecc::CxError; -use messages::StatusWord; +use mintlayer_messages::StatusWord; pub fn cx_err_to_status(e: CxError) -> StatusWord { match e { diff --git a/src/handlers/get_public_key.rs b/crates/app-core/src/handlers/get_public_key.rs similarity index 87% rename from src/handlers/get_public_key.rs rename to crates/app-core/src/handlers/get_public_key.rs index 3d0c63a..86b7c44 100644 --- a/src/handlers/get_public_key.rs +++ b/crates/app-core/src/handlers/get_public_key.rs @@ -17,15 +17,20 @@ use crate::app_ui::address::ui_display_pk; use crate::StatusWord; -use messages::{mlcp::CoinType, ChainCode, GetPublicKeyResponse, PublicKey, PublicKeyReq}; +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() < 3 { + if req.path.as_ref().len() < MIN_PATH_LEN { return Err(StatusWord::InvalidPath); } let coin_type: CoinType = req.coin_type.into(); diff --git a/src/handlers/sign_message.rs b/crates/app-core/src/handlers/sign_message.rs similarity index 89% rename from src/handlers/sign_message.rs rename to crates/app-core/src/handlers/sign_message.rs index 1075fc9..5a60d55 100644 --- a/src/handlers/sign_message.rs +++ b/crates/app-core/src/handlers/sign_message.rs @@ -19,8 +19,8 @@ use crate::{ app_ui::sign::ui_display_message, errors::cx_err_to_status, handlers::utils::mintlayer_hash, DataContext, StatusWord, }; -use messages::{ - mlcp::CoinType, AddrType, Bip32Path, MsgSignatureResponse, SignMessageReq, Signature, +use mintlayer_messages::{ + mlcp::CoinType, AddrType, Bip32Path, MsgSignatureResponse, SignMessageReq, SignatureResponse, }; use alloc::vec::Vec; @@ -49,20 +49,14 @@ impl SignMessageContext { } } -pub fn setup_sign_message(req: SignMessageReq, ctx: &mut DataContext) -> Result<(), StatusWord> { - *ctx = DataContext::SignMessageContext(SignMessageContext::new(req)); - Ok(()) +pub fn setup_sign_message(req: SignMessageReq) -> DataContext { + DataContext::SignMessageContext(SignMessageContext::new(req)) } pub fn handle_sign_message( message: &[u8], - ctx: &mut DataContext, + ctx: &mut SignMessageContext, ) -> Result { - let ctx = match ctx { - DataContext::SignMessageContext(ctx) => ctx, - _ => return Err(StatusWord::WrongContext), - }; - let private_key = Secp256k1::derive_from_path(ctx.path.as_ref()); let public_key = private_key .public_key() @@ -100,7 +94,7 @@ fn compute_signature( let sig = schnorr_sign(private_key, message_hash2.as_bytes())?; let response = MsgSignatureResponse { - signature: Signature(sig), + signature: SignatureResponse(sig), }; Ok(response) 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..c9f627f --- /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: Box, + 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: Box, + 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, ctx, review)? + } + (SignTxReq::Output(req), TxParsingContext::ParsingOutputs(ctx)) => { + handle_output_req(req, 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/src/handlers/sign_tx/summary_collector.rs b/crates/app-core/src/handlers/sign_tx/summary_collector.rs similarity index 55% rename from src/handlers/sign_tx/summary_collector.rs rename to crates/app-core/src/handlers/sign_tx/summary_collector.rs index f8a7403..a62da2a 100644 --- a/src/handlers/sign_tx/summary_collector.rs +++ b/crates/app-core/src/handlers/sign_tx/summary_collector.rs @@ -18,13 +18,11 @@ use alloc::collections::BTreeMap; use crate::StatusWord; -use messages::{ +use mintlayer_messages::{ mlcp::{ - AccountCommand, AccountSpending, Amount, OrderAccountCommand, - TxOutput, H256, OutputValue, + AccountCommand, AccountSpending, Amount, OrderAccountCommand, OutputValue, TxOutput, H256, }, - AdditionalOrderInfo, AdditionalUtxoInfo, - TxInputWithAdditionalInfo, + AdditionalOrderInfo, AdditionalUtxoInfo, TxInputWithAdditionalInfo, }; #[derive(Eq, Ord, PartialEq, PartialOrd)] @@ -56,12 +54,19 @@ pub enum TxType { FreezeOrder, CreateOrder, ConcludeOrder, - ComplexTransaction, 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, } @@ -70,11 +75,16 @@ 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 } @@ -90,19 +100,21 @@ impl TxSummaryCollector { 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::TxNumericOperationFail)?; - - Ok((coin_or_token, fee)) - }) + 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> { @@ -147,8 +159,11 @@ impl TxSummaryCollector { TxOutput::IssueNft(_, _, _) => { self.tx_type = merge_tx_type(self.tx_type, TxType::CreateNft); } - TxOutput::CreateOrder(_) => { + 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)?; } } @@ -162,6 +177,7 @@ impl TxSummaryCollector { 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) => { @@ -170,7 +186,7 @@ impl TxSummaryCollector { | TxOutput::LockThenTransfer(value, _, _) | TxOutput::Htlc(value, _) => { let (coin_or_token_id, amount) = - into_coin_or_token_id_and_amount(&value)?; + into_coin_or_token_id_and_amount(value)?; self.increase_input_totals(coin_or_token_id, amount)?; } TxOutput::Burn(_) @@ -192,42 +208,48 @@ impl TxSummaryCollector { }; } }, - TxInputWithAdditionalInfo::Account(acc) => match acc.spending { - AccountSpending::DelegationBalance(_, amount) => { - self.tx_type = merge_tx_type(self.tx_type, TxType::DelegationWithdrawl); - self.increase_input_totals(CoinOrTokenId::Coin, amount)?; + 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::DelegationWithdrawl); + self.increase_input_totals(CoinOrTokenId::Coin, amount)?; + } } - }, - TxInputWithAdditionalInfo::AccountCommand(_, cmd) => 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::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 { @@ -236,39 +258,44 @@ impl TxSummaryCollector { ask_balance, give_balance, }, - ) => 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)?; + ) => { + 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)?; - 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.increase_output_totals(fill_coin_or_token_id, *fill_amount)?; - self.tx_type = merge_tx_type(self.tx_type, TxType::ConcludeOrder); - } - OrderAccountCommand::FreezeOrder(_) => { - self.tx_type = merge_tx_type(self.tx_type, TxType::FreezeOrder); + 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(()) @@ -279,7 +306,10 @@ impl TxSummaryCollector { key: CoinOrTokenId, amount: Amount, ) -> Result<(), StatusWord> { - let total = self.total_inputs.entry(key).or_insert(Amount::from_atoms(0)); + let total = self + .total_inputs + .entry(key) + .or_insert(Amount::from_atoms(0)); let new_total = total .into_atoms() .checked_add(amount.into_atoms()) @@ -293,7 +323,10 @@ impl TxSummaryCollector { key: CoinOrTokenId, amount: Amount, ) -> Result<(), StatusWord> { - let total = self.total_outputs.entry(key).or_insert(Amount::from_atoms(0)); + let total = self + .total_outputs + .entry(key) + .or_insert(Amount::from_atoms(0)); let new_total = total .into_atoms() .checked_add(amount.into_atoms()) @@ -322,3 +355,44 @@ fn into_coin_or_token_id_and_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, + )), + )); + + 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/src/handlers/utils.rs b/crates/app-core/src/handlers/utils.rs similarity index 97% rename from src/handlers/utils.rs rename to crates/app-core/src/handlers/utils.rs index 1367672..d43404b 100644 --- a/src/handlers/utils.rs +++ b/crates/app-core/src/handlers/utils.rs @@ -17,7 +17,7 @@ use crate::StatusWord; -use messages::mlcp::H256; +use mintlayer_messages::mlcp::H256; use ledger_device_sdk::hash::{blake2::Blake2b_512, HashInit}; diff --git a/crates/app-core/src/lib.rs b/crates/app-core/src/lib.rs new file mode 100644 index 0000000..6465518 --- /dev/null +++ b/crates/app-core/src/lib.rs @@ -0,0 +1,352 @@ +/***************************************************************************** + * + * 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 handlers::{ + get_public_key::handle_get_public_key, + sign_message::{handle_sign_message, setup_sign_message, SignMessageContext}, + 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, +}; + +use crate::handlers::sign_tx::handle_sign_tx; + +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(|_| StatusWord::WrongApduLength)?; + + // 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/messages/src/lib.rs b/crates/messages/src/lib.rs similarity index 91% rename from messages/src/lib.rs rename to crates/messages/src/lib.rs index 16cfe8a..7eb2699 100644 --- a/messages/src/lib.rs +++ b/crates/messages/src/lib.rs @@ -20,7 +20,7 @@ // Required for using String, Vec, format!... extern crate alloc; -use alloc::vec::Vec; +use alloc::{boxed::Box, vec::Vec}; use core::iter::ExactSizeIterator; use derive_more::Display; @@ -95,9 +95,9 @@ pub struct SignMessageReq { #[derive(Encode, Decode)] pub enum SignTxReq { - Input(TxInputReq), - InputCommitment(mlcp::SighashInputCommitment), - Output(TxOutputReq), + Input(Box), + InputCommitment(Box), + Output(Box), NextSignature, } @@ -269,11 +269,11 @@ pub struct GetPublicKeyResponse { } #[derive(Encode, Decode)] -pub struct Signature(pub [u8; 64]); +pub struct SignatureResponse(pub [u8; 64]); #[derive(Encode, Decode)] pub struct TxInputSignatureResponse { - pub signature: Signature, + pub signature: SignatureResponse, pub input_idx: u32, pub multisig_idx: Option, pub has_next: bool, @@ -281,7 +281,7 @@ pub struct TxInputSignatureResponse { #[derive(Encode, Decode)] pub struct MsgSignatureResponse { - pub signature: Signature, + pub signature: SignatureResponse, } #[derive(Encode, Decode)] @@ -340,7 +340,7 @@ impl<'a> Apdu<'a> { param1_byte: u8, command_data: &'a [u8], ) -> Option { - (command_data.len() <= MAX_ADPU_DATA_LEN).then(|| Self { + (command_data.len() <= MAX_ADPU_DATA_LEN).then_some(Self { instruction_byte, param1_byte, command_data, @@ -416,50 +416,44 @@ pub enum StatusWord { // App Specific Errors (0xB...) #[display("Transaction display failed")] TxDisplayFail = 0xB000, - #[display("Address display failed")] - AddrDisplayFail = 0xB001, + #[display("Transaction lock time value is invalid")] + TxLockTimeInvalid = 0xB001, #[display("Transaction wrong length")] TxWrongLength = 0xB002, - #[display("Transaction parsing failed")] - TxParsingFail = 0xB003, #[display("Transaction hashing failed")] - TxHashFail = 0xB004, + TxHashFail = 0xB003, #[display("Transaction address failed")] - TxAddressFail = 0xB005, - #[display("Transaction signing failed")] - TxSignFail = 0xB006, + TxAddressFail = 0xB004, + #[display("Different instruction than expected")] + WrongInstruction = 0xB005, #[display("Key derivation failed")] - KeyDeriveFail = 0xB007, - #[display("Version parsing failed")] - VersionParsingFail = 0xB008, + KeyDeriveFail = 0xB006, + #[display("Orders V0 not supported")] + OrdersV0NotSupported = 0xB007, #[display("Wrong context")] - WrongContext = 0xB009, + WrongContext = 0xB008, #[display("Deserialization failed")] - DeserializeFail = 0xB00A, + DeserializeFail = 0xB009, #[display("Invalid input UTXO")] - TxInvalidInputUtxo = 0xB00B, + TxInvalidInputUtxo = 0xB00A, #[display("Numeric operation failed")] - TxNumericOperationFail = 0xB00C, - #[display("Unsupported input")] - TxUnsupportedInput = 0xB00D, - #[display("Invalid Token V0")] - TxInvalidTokenV0 = 0xB00E, + TxNumericOperationFail = 0xB00B, + #[display("Tx fee underflow")] + TxFeeUnderflow = 0xB00C, #[display("Invalid input path")] - TxInvalidInputPath = 0xB00F, + TxInvalidInputPath = 0xB00D, #[display("Nothing to sign")] - NothingToSign = 0xB010, + NothingToSign = 0xB00E, #[display("Transaction already finished")] - TxAlreadyFinished = 0xB011, + TxAlreadyFinished = 0xB00F, #[display("Invalid path")] - InvalidPath = 0xB012, + InvalidPath = 0xB010, #[display("Invalid uncompressed public key")] - InvalidUncompressedPublicKey = 0xB013, + InvalidUncompressedPublicKey = 0xB011, #[display("Max buffer length exceeded")] - MaxBufferLenExceeded = 0xB014, + MaxBufferLenExceeded = 0xB012, #[display("Different input commitment hash")] - DifferentInputCommitmentHash = 0xB015, - #[display("Orders V0 not supported")] - OrdersV0NotSupported = 0xB016, + DifferentInputCommitmentHash = 0xB013, // Ecc Errors #[display("ECC Carry")] 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/messages/Cargo.toml b/messages/Cargo.toml deleted file mode 100644 index aed18f0..0000000 --- a/messages/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "messages" -version = "0.1.0" -edition = "2024" - -[dependencies] -# 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. -parity-scale-codec = { git = "https://github.com/paritytech/parity-scale-codec.git", rev = "5021525697edc0661591ebc71392c48d950a10b0", default-features = false, features = [ - "derive", - "chain-error", -] } - -num_enum = { version = "0.7.5", default-features = false } -derive_more = { version = "2.1.1", default-features = false, features = [ - "display", -] } - -[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" diff --git a/run_extra_checks.sh b/run_extra_checks.sh new file mode 100755 index 0000000..27437e1 --- /dev/null +++ b/run_extra_checks.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +set -e +set -o nounset + +# Run some extra checks (for now its mostly clippy). + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) + +cd "$SCRIPT_DIR" + +echo "Running cargo fmt" +cargo fmt --check -- --config newline_style=Unix + +# It doesn't matter which one we use, but we need to specify one. +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/src/handlers/sign_tx/mod.rs b/src/handlers/sign_tx/mod.rs deleted file mode 100644 index 86ecfdf..0000000 --- a/src/handlers/sign_tx/mod.rs +++ /dev/null @@ -1,638 +0,0 @@ -/***************************************************************************** - * 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 alloc::vec::Vec; - -use crate::{ - app_ui::sign::{ - approve_streaming_review, new_streaming_review, start_streaming_review, - streaming_review_show_output, ui_display_tx, - }, - handlers::{sign_message::schnorr_sign, utils::mintlayer_hash}, - DataContext, StatusWord, -}; -use messages::{ - encode_as_compact, encode_to, - mlcp::{ - Amount, CoinType as PCoinType, - SighashInputCommitment, TxOutput, H256, - }, - CoinType, Encode, InputAddressPath, Response, - SignTxReq, Signature, 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::{TxType, CoinOrTokenId}; - -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; - -pub struct InputCompressed { - pub path: [u32; COMPRESSED_DERIVATION_PATH_LEN], - pub input_idx: u32, - pub multisig_idx: Option, -} - -impl InputCompressed { - fn new(addr: InputAddressPath, input_idx: u32, 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, - }) - } -} - -#[derive(PartialEq, Eq)] -enum TxParsingState { - Input(u32), - InputCommitment { - inp_idx: u32, - input_commitments_hash: [u8; 64], - }, - Output(u32), - CompleteNotApproved { - inp_idx: u32, - sighash: H256, - }, - ApprovedNotFinishedSigning { - inp_idx: u32, - sighash: H256, - }, - Finished, -} - -#[derive(PartialEq, Eq)] -pub enum NextTxOutputParsingState { - Output(u32), - CompleteNotApproved { inp_idx: u32, sighash: H256 }, -} - -pub struct TxContext { - raw_buf: Vec, - coin: PCoinType, - num_inputs: u32, - num_outputs: u32, - review_finished: bool, - state: TxParsingState, - - tx_hasher: Blake2b_512, - input_commitments_hasher: Blake2b_512, - - summary: TxSummaryCollector, - inputs: Vec, - - spinner: NbglSpinner, -} - -pub enum Review { - Review(Vec), - StreamingReview(NbglStreamingReview), -} - -pub enum SigningState<'a> { - StreamingReviewStart(&'a NbglStreamingReview), - StreamingReviewOutput(&'a NbglStreamingReview, TxOutput), - StreamingReviewApprove { - review: &'a NbglStreamingReview, - output: TxOutput, - inp_idx: u32, - sighash: H256, - }, - TxParsingNotComplete, - CompleteNotApproved { - inp_idx: u32, - sighash: H256, - outputs: &'a [TxOutput], - }, - ApprovedNotFinishedSigning { - inp_idx: u32, - sighash: H256, - }, -} - -impl TxContext { - 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)?; - - Ok(TxContext { - coin: coin.into(), - raw_buf: Vec::with_capacity(251), - num_inputs, - num_outputs, - review_finished: false, - tx_hasher, - input_commitments_hasher: Blake2b_512::new(), - state: TxParsingState::Input(0), - summary: TxSummaryCollector::new(), - inputs: Vec::with_capacity(20), - spinner: NbglSpinner::new(), - }) - } - - pub fn coin(&self) -> PCoinType { - self.coin - } - - pub fn summary(&self) -> &TxSummaryCollector { - &self.summary - } - - pub fn summary_mut(&mut self) -> &mut TxSummaryCollector { - &mut self.summary - } - - pub fn tx_type(&self) -> Option { - self.summary.tx_type() - } - - pub fn total_inputs(&self) -> &BTreeMap { - self.summary.total_inputs() - } - - pub fn total_outputs(&self) -> &BTreeMap { - self.summary.total_outputs() - } - - fn state(&self) -> &TxParsingState { - &self.state - } - - fn update_hash(&mut self, data: &T) -> Result<(), StatusWord> { - update_hash(&mut self.raw_buf, data, &mut self.tx_hasher) - } - - fn update_input_commitments_hash(&mut self, data: &T) -> Result<(), StatusWord> { - update_hash(&mut self.raw_buf, data, &mut self.input_commitments_hasher) - } - - fn completed_all_signatures(&self) -> bool { - self.state == TxParsingState::Finished - } - - // Get review status - #[allow(dead_code)] - pub fn finished(&self) -> bool { - self.review_finished - } - - fn advance_next_input_step<'a>( - &mut self, - current_input_step: u32, - ) -> Result, StatusWord> { - let finished_with_inputs = current_input_step >= (self.num_inputs - 1); - - self.state = if finished_with_inputs { - // Update hash for input commitments and proceed with outputs - self.tx_hasher - .update(&self.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)?; - - self.input_commitments_hasher = Blake2b_512::new(); - - TxParsingState::InputCommitment { - inp_idx: 0, - input_commitments_hash, - } - } else { - TxParsingState::Input(current_input_step + 1) - }; - - Ok(SigningState::TxParsingNotComplete) - } - - fn advance_next_input_additional_info_step<'a>( - &mut self, - current_input_step: u32, - expected_input_commitments_hash: [u8; 64], - review: &'a Review, - ) -> Result, StatusWord> { - let finished_with_inputs = current_input_step >= (self.num_inputs - 1); - - let signing_state = 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 != expected_input_commitments_hash { - return Err(StatusWord::DifferentInputCommitmentHash); - } - - self.state = TxParsingState::Output(0); - - match review { - Review::Review(_) => SigningState::TxParsingNotComplete, - Review::StreamingReview(review) => SigningState::StreamingReviewStart(review), - } - } else { - self.state = TxParsingState::InputCommitment { - inp_idx: current_input_step + 1, - input_commitments_hash: expected_input_commitments_hash, - }; - SigningState::TxParsingNotComplete - }; - - Ok(signing_state) - } - - // After processing an output advance the internal state - fn advance_next_output_state( - &mut self, - n: u32, - ) -> Result { - let next_state = if n < (self.num_outputs - 1) { - NextTxOutputParsingState::Output(n + 1) - } else { - let inp_idx = 0; - // 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 message_hash2 = mintlayer_hash(&message_hash[0..32])?; - - NextTxOutputParsingState::CompleteNotApproved { - inp_idx, - sighash: message_hash2, - } - }; - - self.state = match next_state { - NextTxOutputParsingState::Output(out) => TxParsingState::Output(out), - NextTxOutputParsingState::CompleteNotApproved { inp_idx, sighash } => { - TxParsingState::CompleteNotApproved { inp_idx, sighash } - } - }; - - Ok(next_state) - } - - // After processing a signature advance the internal state - fn advance_next_signing_step(&mut self, inp_idx: u32, sighash: &H256) { - self.state = if ((inp_idx + 1) as usize) < self.inputs.len() { - TxParsingState::ApprovedNotFinishedSigning { - inp_idx: inp_idx + 1, - sighash: *sighash, - } - } else { - TxParsingState::Finished - }; - } - - // show a spinner for bigger transactions - pub fn show_spinner(&mut self) { - let is_transaction_big = self.num_inputs * 2 + self.num_outputs > 10; - let returning_signatures = match self.state { - TxParsingState::ApprovedNotFinishedSigning { - inp_idx: _, - sighash: _, - } - | TxParsingState::CompleteNotApproved { - inp_idx: _, - sighash: _, - } => true, - TxParsingState::Input(_) - | TxParsingState::InputCommitment { - inp_idx: _, - input_commitments_hash: _, - } - | TxParsingState::Finished - | TxParsingState::Output(_) => false, - }; - - if returning_signatures && self.num_inputs > 1 { - self.spinner.show("Signing..."); - } else if is_transaction_big { - self.spinner.show("Parsing transaction..."); - } - } -} - -pub fn setup_sign_tx(req: TxMetadataReq, ctx: &mut DataContext) -> Result<(), StatusWord> { - let mut tx_ctx = match req.version { - TxMetadataVersionReq::V1(v1_req) => TxContext::from_v1(req.coin, v1_req)?, - }; - - tx_ctx.show_spinner(); - - // if the tx has many outputs use a streaming review - if tx_ctx.num_outputs > 10 { - *ctx = DataContext::TxContext(tx_ctx, Review::StreamingReview(new_streaming_review())); - } else { - *ctx = DataContext::TxContext(tx_ctx, Review::Review(Vec::new())); - } - - Ok(()) -} - -fn handle_input_commitment_req<'a>( - req: SighashInputCommitment, - input_step: u32, - input_commitments_hash: [u8; 64], - ctx: &mut TxContext, - review: &'a mut Review, -) -> Result, StatusWord> { - ctx.update_input_commitments_hash(&req)?; - ctx.update_hash(&req)?; - ctx.advance_next_input_additional_info_step(input_step, input_commitments_hash, review) -} - -fn handle_input_req<'a>( - req: TxInputReq, - input_step: u32, - ctx: &mut TxContext, -) -> Result, StatusWord> { - let addresses = req - .addresses - .into_iter() - .map(|a| InputCompressed::new(a, input_step, ctx.coin)) - .collect::, StatusWord>>()?; - ctx.inputs.extend(addresses); - - ctx.summary.process_input(&req.inp)?; - - let (input, commitment) = req.inp.into_input_and_commitment(); - ctx.update_input_commitments_hash(&commitment)?; - - if input_step == 0 { - ctx.tx_hasher - .update(&ctx.num_inputs.to_le_bytes()) - .map_err(|_| StatusWord::TxHashFail)?; - } - ctx.update_hash(&input)?; - ctx.advance_next_input_step(input_step) -} - -fn handle_output_req<'a>( - req: TxOutputReq, - output_step: u32, - ctx: &mut TxContext, - review: &'a mut Review, -) -> Result, StatusWord> { - ctx.summary.process_output(&req.out)?; - // on the first output add the number of outputs to the hash - if output_step == 0 { - ctx.tx_hasher - .update(&encode_as_compact(ctx.num_outputs)) - .map_err(|_| StatusWord::TxHashFail)?; - } - ctx.update_hash(&req.out)?; - let next_step = ctx.advance_next_output_state(output_step)?; - let signin_state = match review { - Review::Review(outputs) => { - outputs.push(req.out); - match next_step { - NextTxOutputParsingState::Output(_) => SigningState::TxParsingNotComplete, - NextTxOutputParsingState::CompleteNotApproved { inp_idx, sighash } => { - SigningState::CompleteNotApproved { - inp_idx, - sighash, - outputs, - } - } - } - } - Review::StreamingReview(review) => { - // on last output show it and ask for approval - match next_step { - NextTxOutputParsingState::Output(_) => { - SigningState::StreamingReviewOutput(review, req.out) - } - NextTxOutputParsingState::CompleteNotApproved { inp_idx, sighash } => { - SigningState::StreamingReviewApprove { - review, - output: req.out, - inp_idx, - sighash, - } - } - } - } - }; - - Ok(signin_state) -} - -pub fn handle_sign_tx( - req: SignTxReq, - ctx: &mut TxContext, - review: &mut Review, -) -> Result { - let signing_state = match (req, ctx.state()) { - (SignTxReq::Input(req), TxParsingState::Input(n)) => handle_input_req(req, *n, ctx)?, - ( - SignTxReq::InputCommitment(req), - TxParsingState::InputCommitment { - inp_idx, - input_commitments_hash, - }, - ) => handle_input_commitment_req(req, *inp_idx, *input_commitments_hash, ctx, review)?, - (SignTxReq::Output(req), TxParsingState::Output(n)) => { - handle_output_req(req, *n, ctx, review)? - } - ( - SignTxReq::NextSignature, - TxParsingState::ApprovedNotFinishedSigning { inp_idx, sighash }, - ) => SigningState::ApprovedNotFinishedSigning { - inp_idx: *inp_idx, - sighash: *sighash, - }, - ( - SignTxReq::NextSignature, - TxParsingState::CompleteNotApproved { - inp_idx: _, - sighash: _, - }, - ) => return Err(StatusWord::Deny), - (SignTxReq::NextSignature, TxParsingState::Finished) => { - return Err(StatusWord::TxAlreadyFinished) - } - (_, _) => return Err(StatusWord::WrongP1P2), - }; - - match signing_state { - SigningState::TxParsingNotComplete => Ok(Response::TxNext), - SigningState::StreamingReviewStart(review) => { - if start_streaming_review(review) { - Ok(Response::TxNext) - } else { - ctx.review_finished = true; - Err(StatusWord::Deny) - } - } - SigningState::StreamingReviewOutput(review, output) => { - if streaming_review_show_output(review, &output, ctx.coin)? { - Ok(Response::TxNext) - } else { - ctx.review_finished = true; - Err(StatusWord::Deny) - } - } - SigningState::StreamingReviewApprove { - review, - output, - inp_idx, - sighash, - } => { - if approve_streaming_review(review, &output, ctx)? { - let response = compute_signature_and_append(ctx, inp_idx, &sighash)?; - if ctx.completed_all_signatures() { - ctx.review_finished = true; - } else { - ctx.show_spinner(); - } - Ok(Response::TxSignature(response)) - } else { - ctx.review_finished = true; - Err(StatusWord::Deny) - } - } - SigningState::CompleteNotApproved { - inp_idx, - sighash, - outputs, - } => { - // Display transaction. If user approves the transaction, sign it. - // Otherwise, return a "deny" status word. - if ui_display_tx(ctx, outputs)? { - let response = compute_signature_and_append(ctx, inp_idx, &sighash)?; - if ctx.completed_all_signatures() { - ctx.review_finished = true; - } else { - ctx.show_spinner(); - } - - Ok(Response::TxSignature(response)) - } else { - ctx.review_finished = true; - Err(StatusWord::Deny) - } - } - SigningState::ApprovedNotFinishedSigning { inp_idx, sighash } => { - // Already approved sign and return the next signature - let response = compute_signature_and_append(ctx, inp_idx, &sighash)?; - if ctx.completed_all_signatures() { - ctx.review_finished = true; - } else { - ctx.show_spinner(); - } - - Ok(Response::TxSignature(response)) - } - } -} - - -fn compute_signature_and_append( - ctx: &mut TxContext, - inp_idx: u32, - sighash: &H256, -) -> Result { - let address = ctx - .inputs - .get(inp_idx as usize) - .ok_or(StatusWord::WrongContext)?; - - let [p1, p2, p3] = address.path; - let addr = [BIP44, ctx.coin.bip44_coin_type(), p1, p2, p3]; - - let private_key = Secp256k1::derive_from_path(&addr); - let sig = schnorr_sign(&private_key, sighash.as_bytes())?; - - let signature = Signature(sig); - let input_idx = address.input_idx; - let multisig_idx = address.multisig_idx; - - ctx.advance_next_signing_step(inp_idx, sighash); - let response = TxInputSignatureResponse { - signature, - multisig_idx, - input_idx, - has_next: ctx.state != TxParsingState::Finished, - }; - - Ok(response) -} - -fn update_hash( - raw_buf: &mut Vec, - data: &T, - hasher: &mut Blake2b_512, -) -> Result<(), StatusWord> { - raw_buf.clear(); - encode_to(data, raw_buf); - hasher - .update(raw_buf.as_slice()) - .map_err(|_| StatusWord::TxHashFail)?; - raw_buf.clear(); - Ok(()) -} diff --git a/src/main.rs b/src/main.rs index 0f7e143..1b527f4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,302 +19,11 @@ #![no_std] #![no_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; - -// 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, StatusType}, -}; - -use app_ui::menu::ui_menu_main; -use handlers::{ - get_public_key::handle_get_public_key, - sign_message::{handle_sign_message, setup_sign_message, SignMessageContext}, - sign_tx::{setup_sign_tx, Review, TxContext}, -}; -use messages::{ - decode_all, encode, Ins, PubKeyP1, Response, SignP1, StatusWord, APDU_CLASS, MAX_ADPU_DATA_LEN, - P2_DONE, P2_MORE, -}; - -use crate::handlers::sign_tx::handle_sign_tx; +use mintlayer_app_core::mintlayer_main; ledger_device_sdk::set_panic!(ledger_device_sdk::exiting_panic); -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 ApduTransport { - pub fn new() -> Self { - Self { - buffer: Vec::with_capacity(255), // Pre-alloc for at least one standard APDU - current_ins: None, - current_p1: None, - } - } - - /// 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(|_| StatusWord::WrongApduLength)?; - - // 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 || 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 { - 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 Context, 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 { - Empty, - TxContext(TxContext, Review), - SignMessageContext(SignMessageContext), -} - -struct Context { - pub data: DataContext, - pub home: NbglHomeAndSettings, -} - -impl Context { - fn new() -> Self { - Self { - data: DataContext::Empty, - home: Default::default(), - } - } - - fn finished(&self) -> bool { - match &self.data { - DataContext::Empty => false, - DataContext::SignMessageContext(ctx) => ctx.finished(), - DataContext::TxContext(ctx, _) => ctx.finished(), - } - } -} - #[no_mangle] extern "C" fn sample_main() { - let mut comm = Comm::new().set_expected_cla(APDU_CLASS); - - let mut tx_ctx = Context::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::new(); - - 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 Context) -> 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)?; - setup_sign_tx(req, &mut ctx.data)?; - Ok(Response::TxSetup) - } - SignP1::Next => { - let (tx_ctx, review) = match &mut ctx.data { - DataContext::TxContext(c, r) => (c, r), - _ => return Err(StatusWord::WrongContext), - }; - - tx_ctx.show_spinner(); - - let req = decode_all(data).ok_or(StatusWord::DeserializeFail)?; - handle_sign_tx(req, tx_ctx, review) - } - }, - Command::SignMessage { p1, data } => match p1 { - SignP1::Start => { - let req = decode_all(&data).ok_or(StatusWord::DeserializeFail)?; - setup_sign_message(req, &mut ctx.data)?; - Ok(Response::MessageSetup) - } - SignP1::Next => { - handle_sign_message(&data, &mut ctx.data).map(Response::MessageSignature) - } - }, - Command::Ping => Ok(Response::Pong), - } + mintlayer_main(); } diff --git a/tests/application_client/__init__.py b/tests/application_client/__init__.py index 471539e..dff703e 100644 --- a/tests/application_client/__init__.py +++ b/tests/application_client/__init__.py @@ -392,15 +392,26 @@ def init_mintlayer_types(): ["signature", "Signature"], ], }, - "TxMetadataReq": { + "TxMetadataVersionReq": { + "type": "enum", + "type_mapping": [ + ["V1", "TxMetadataV1Req"], + ], + }, + "TxMetadataV1Req": { "type": "struct", "type_mapping": [ - ["coin", "u8"], - ["version", "u8"], ["num_inputs", "u32"], ["num_outputs", "u32"], ], }, + "TxMetadataReq": { + "type": "struct", + "type_mapping": [ + ["coin", "u8"], + ["version", "TxMetadataVersionReq"], + ], + }, "TxInputReq": { "type": "struct", "type_mapping": [ @@ -442,17 +453,48 @@ def init_mintlayer_types(): ["NextSignature", "()"], ], }, + "SignatureResponse": "[u8; 64]", "MsgSignature": { "type": "struct", "type_mapping": [ - ["signature", "[u8; 64]"], + ["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", "[u8; 65]"], - ["chain_code", "[u8; 32]"], + ["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": { diff --git a/tests/application_client/mintlayer_command_sender.py b/tests/application_client/mintlayer_command_sender.py index b5f7aca..e1ca862 100644 --- a/tests/application_client/mintlayer_command_sender.py +++ b/tests/application_client/mintlayer_command_sender.py @@ -1,9 +1,12 @@ 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 @@ -14,20 +17,34 @@ "SignTxReq" ) -MAX_APDU_LEN: int = 255 - 5 # 255 - CLA, INS, P1, P2, Lc +MAX_APDU_LEN: int = 255 +TX_RESPONSE_SIZE: int = 71 CLA: int = 0xE1 -class P1(IntEnum): +@dataclass +class SignTxStep: + kind: str + index: int | None = None + +class GetAppAndVersionP1(IntEnum): # Parameter 1 for first APDU number. P1_START = 0x00 - P1_TX_INPUT = 0x01 - P1_TX_INPUT_COMMITMENT = 0x02 - P1_TX_OUTPUT = 0x03 - P1_TX_NEXT_SIG = 0x04 - # Parameter 1 for maximum APDU number. - P1_MAX = 0x03 + 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 @@ -48,15 +65,16 @@ class InsType(IntEnum): class Errors(IntEnum): SW_DENY = 0x6985 SW_CLA_NOT_SUPPORTED = 0x6E00 - SW_INS_NOT_SUPPORTED = 0x6E01 - SW_WRONG_P1P2 = 0x6E02 + SW_INS_NOT_SUPPORTED = 0x6D00 + SW_WRONG_P1P2 = 0x6B00 SW_WRONG_APDU_LENGTH = 0x6E03 + SW_WRONG_RESPONSE_LENGTH = 0xB000 SW_DISPLAY_BIP32_PATH_FAIL = 0xB001 SW_WRONG_TX_LENGTH = 0xB002 - SW_WRONG_CONTEXT = 0xB009 - SW_DESERIALIZE_FAIL = 0xB00A - SW_MAX_BUFFER_LEN_EXCEEDED = 0xB014 + SW_WRONG_CONTEXT = 0xB008 + SW_DESERIALIZE_FAIL = 0xB009 + SW_MAX_BUFFER_LEN_EXCEEDED = 0xB012 def split_message(message: bytes, max_size: int) -> List[bytes]: @@ -71,7 +89,7 @@ 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=P1.P1_START, + p1=GetAppAndVersionP1.P1_START, p2=P2.P2_LAST, data=b"", ) @@ -82,7 +100,7 @@ def get_public_key(self, coin: int, path: str) -> RAPDU: return self.backend.exchange( cla=CLA, ins=InsType.GET_PUBLIC_KEY, - p1=P1.P1_START, + p1=GetPublicKeyP1.P1_START, p2=P2.P2_LAST, data=data, ) @@ -96,7 +114,7 @@ def get_public_key_with_confirmation( with self.backend.exchange_async( cla=CLA, ins=InsType.GET_PUBLIC_KEY, - p1=P1.P1_CONFIRM, + p1=GetPublicKeyP1.P1_CONFIRM, p2=P2.P2_LAST, data=data, ) as response: @@ -113,121 +131,127 @@ def sign_message( ) self.backend.exchange( - cla=CLA, ins=InsType.SIGN_MESSAGE, p1=P1.P1_START, p2=P2.P2_LAST, data=data + cla=CLA, ins=InsType.SIGN_MESSAGE, p1=SignMessageP1.P1_START, p2=P2.P2_LAST, data=data ) - messages = split_message(message, MAX_APDU_LEN) - idx: int = P1.P1_START + 1 + chunks = split_message(message, MAX_APDU_LEN) - for msg in messages[:-1]: + for chunk in chunks[:-1]: self.backend.exchange( - cla=CLA, ins=InsType.SIGN_MESSAGE, p1=idx, p2=P2.P2_MORE, data=msg + 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=idx, p2=P2.P2_LAST, data=messages[-1] + cla=CLA, ins=InsType.SIGN_MESSAGE, p1=SignMessageP1.P1_NEXT, p2=P2.P2_LAST, data=chunks[-1] ) as response: yield response - @contextmanager - def sign_tx(self, transaction: Transaction) -> Generator[None, None, None]: + def sign_tx(self, transaction: Transaction) -> Generator[SignTxStep, None, None]: + # ---- METADATA ---- metadata = tx_metadata_obj.encode( { "coin": transaction.coin, - "version": 1, - "num_inputs": len(transaction.inputs), - "num_outputs": len(transaction.outputs), + "version": { + "V1": { + "num_inputs": len(transaction.inputs), + "num_outputs": len(transaction.outputs), + }, + }, } ).data res = self.backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_START, + 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: - chunks = split_message(inp, MAX_APDU_LEN) - for chunk in chunks[:-1]: - res = self.backend.exchange( - cla=CLA, - ins=InsType.SIGN_TX, - p1=P1.P1_TX_INPUT, - p2=P2.P2_MORE, - data=chunk, - ) - print("inp chunk ", res) + self._send_chunked_sync(inp) - res = self.backend.exchange( - cla=CLA, - ins=InsType.SIGN_TX, - p1=P1.P1_TX_INPUT, - p2=P2.P2_LAST, - data=chunks[-1], - ) - print("inp ", res) + # ---- INPUT COMMITMENTS ---- + print("sending input commitments") - for inp in transaction.input_commitments: - chunks = split_message(inp, MAX_APDU_LEN) - for chunk in chunks[:-1]: - res = self.backend.exchange( - cla=CLA, - ins=InsType.SIGN_TX, - p1=P1.P1_TX_INPUT_COMMITMENT, - p2=P2.P2_MORE, - data=chunk, - ) + for inp in transaction.input_commitments[:-1]: + self._send_chunked_sync(inp) - res = self.backend.exchange( + 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=P1.P1_TX_INPUT_COMMITMENT, - p2=P2.P2_LAST, - data=chunks[-1], + p1=SignTxP1.P1_NEXT, + p2=P2.P2_MORE, + data=chunk, ) - for out in transaction.outputs[:-1]: + # 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]: - res = self.backend.exchange( + self.backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_TX_OUTPUT, + p1=SignTxP1.P1_NEXT, p2=P2.P2_MORE, data=chunk, ) - print("Out chunk ", res) - res = self.backend.exchange( + + # last chunk async -> UI review + with self.backend.exchange_async( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_TX_OUTPUT, + p1=SignTxP1.P1_NEXT, p2=P2.P2_LAST, data=chunks[-1], - ) - print("Out ", res) + ): + kind = "final" if idx == len(transaction.outputs) - 1 else "output" + yield SignTxStep(kind=kind, index=idx) - chunks = split_message(transaction.outputs[-1], MAX_APDU_LEN) + def _send_chunked_sync(self, data: bytes): + chunks = split_message(data, MAX_APDU_LEN) for chunk in chunks[:-1]: - res = self.backend.exchange( + self.backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_TX_OUTPUT, + p1=SignTxP1.P1_NEXT, p2=P2.P2_MORE, data=chunk, ) - print("Last Out chunk ", res) - with self.backend.exchange_async( + self.backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_TX_OUTPUT, + p1=SignTxP1.P1_NEXT, p2=P2.P2_LAST, data=chunks[-1], - ) as response: - yield response + ) def get_async_response(self) -> Optional[RAPDU]: return self.backend.last_async_response @@ -242,7 +266,7 @@ def get_all_signatures(self, tx: Transaction) -> List[bytes | Any]: res = self.backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_TX_NEXT_SIG, + p1=SignTxP1.P1_NEXT, p2=P2.P2_LAST, data=next_sig, ) @@ -275,3 +299,91 @@ def pack_derivation_path(derivation_path: str) -> bytes: path.append(int(value)) return path_obj.encode(path).data + + +def sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input, 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 \ No newline at end of file diff --git a/tests/application_client/mintlayer_response_unpacker.py b/tests/application_client/mintlayer_response_unpacker.py index 89a2d01..42ad63a 100644 --- a/tests/application_client/mintlayer_response_unpacker.py +++ b/tests/application_client/mintlayer_response_unpacker.py @@ -56,17 +56,18 @@ def unpack_get_app_and_version_response(response: bytes) -> Tuple[str, str]: # chain_code_len (1) # chain_code (var) def unpack_get_public_key_response(response: bytes) -> Tuple[int, bytes, int, bytes]: + print("response bytes: ", len(response)) response_bytes = scalecodec.base.ScaleBytes(response) - msg_signature_obj = scalecodec.base.RuntimeConfiguration().create_scale_object( - "GetPublicKeyResponse", data=response_bytes + response_obj = scalecodec.base.RuntimeConfiguration().create_scale_object( + "Response", data=response_bytes ) - sig = msg_signature_obj.decode() + msg = response_obj.decode() - print(sig) + print(msg) - pub_key = bytes.fromhex(sig["public_key"][2:]) + pub_key = bytes.fromhex(msg["PublicKey"]["public_key"][2:]) pub_key_len = len(pub_key) - chain_code = bytes.fromhex(sig["chain_code"][2:]) + chain_code = bytes.fromhex(msg["PublicKey"]["chain_code"][2:]) chain_code_len = len(chain_code) print(pub_key_len, pub_key) 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..8d17b0f 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..8d17b0f 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 index c0e88bb..f2fa972 100644 Binary files a/tests/snapshots/flex/test_app_mainmenu/00000.png 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 index be844f4..b3f1c85 100644 Binary files a/tests/snapshots/flex/test_app_mainmenu/00001.png and b/tests/snapshots/flex/test_app_mainmenu/00001.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 index c0e88bb..f2fa972 100644 Binary files a/tests/snapshots/flex/test_get_public_key_confirm_accepted/00003.png and b/tests/snapshots/flex/test_get_public_key_confirm_accepted/00003.png differ diff --git a/tests/snapshots/flex/test_sign_message/00004.png b/tests/snapshots/flex/test_sign_message/00004.png index c0e88bb..f2fa972 100644 Binary files a/tests/snapshots/flex/test_sign_message/00004.png and b/tests/snapshots/flex/test_sign_message/00004.png differ diff --git a/tests/snapshots/flex/test_sign_message_pkh/00004.png b/tests/snapshots/flex/test_sign_message_pkh/00004.png index c0e88bb..f2fa972 100644 Binary files a/tests/snapshots/flex/test_sign_message_pkh/00004.png and b/tests/snapshots/flex/test_sign_message_pkh/00004.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 index 45a4df5..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_change_token_authority/00000.png 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/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 index 45a4df5..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_change_token_metadata_uri/00000.png 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/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 index 28682b4..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_create_delegation/00000.png and b/tests/snapshots/flex/test_sign_tx_create_delegation/00000.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 index 28682b4..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_create_stake_pool/00000.png 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/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 index 45a4df5..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_delegation_staking/00000.png and b/tests/snapshots/flex/test_sign_tx_delegation_staking/00000.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 index 45a4df5..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_freeze_tokens/00000.png and b/tests/snapshots/flex/test_sign_tx_freeze_tokens/00000.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 index 28682b4..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_htlc/00000.png and b/tests/snapshots/flex/test_sign_tx_htlc/00000.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 index 28682b4..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_issue_fungible_token/00000.png 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/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 index 28682b4..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_issue_nft/00000.png and b/tests/snapshots/flex/test_sign_tx_issue_nft/00000.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 index 28682b4..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00000.png 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 index 65cbecb..8a8445e 100644 Binary files a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00001.png 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 index 780f8bd..d0597b4 100644 Binary files a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00002.png 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 index 41ed3ff..435aa78 100644 Binary files a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00003.png 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 index 435aa78..f2fa972 100644 Binary files a/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00004.png 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/00010.png b/tests/snapshots/flex/test_sign_tx_lock_then_transfer/00010.png new file mode 100644 index 0000000..bb4b77a 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..bb4b77a 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_mint_tokens/00000.png b/tests/snapshots/flex/test_sign_tx_mint_tokens/00000.png index 28682b4..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_mint_tokens/00000.png and b/tests/snapshots/flex/test_sign_tx_mint_tokens/00000.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 index e22032b..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_order_conclude/00000.png and b/tests/snapshots/flex/test_sign_tx_order_conclude/00000.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 index e22032b..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_order_fill/00000.png and b/tests/snapshots/flex/test_sign_tx_order_fill/00000.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_transfer/00000.png b/tests/snapshots/flex/test_sign_tx_transfer/00000.png index 28682b4..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_transfer/00000.png 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 index 55ea024..67a9b5a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_transfer/00001.png 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 index d7ec2da..77025cd 100644 Binary files a/tests/snapshots/flex/test_sign_tx_transfer/00002.png 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 index 4b294de..435aa78 100644 Binary files a/tests/snapshots/flex/test_sign_tx_transfer/00003.png 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 index 435aa78..f2fa972 100644 Binary files a/tests/snapshots/flex/test_sign_tx_transfer/00004.png and b/tests/snapshots/flex/test_sign_tx_transfer/00004.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 index 45a4df5..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00000.png and b/tests/snapshots/flex/test_sign_tx_unfreeze_tokens/00000.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 index 28682b4..5d42a9a 100644 Binary files a/tests/snapshots/flex/test_sign_tx_unmint_tokens/00000.png and b/tests/snapshots/flex/test_sign_tx_unmint_tokens/00000.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/00001.png b/tests/snapshots/nanosp/test_app_mainmenu/00001.png index bdbc0ff..77bcafd 100644 Binary files a/tests/snapshots/nanosp/test_app_mainmenu/00001.png 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 index 77bcafd..f265d69 100644 Binary files a/tests/snapshots/nanosp/test_app_mainmenu/00002.png and b/tests/snapshots/nanosp/test_app_mainmenu/00002.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/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/00001.png b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00001.png index 2ce4f7e..59d0e80 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00001.png 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 index 3169a43..3d01046 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00002.png 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 index 4100b0b..f62cce2 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00003.png 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 index 46b368c..11e1d3f 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00004.png and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00004.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 index 32a3fd1..17cf916 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_create_delegation/00006.png and b/tests/snapshots/nanosp/test_sign_tx_create_delegation/00006.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/00010.png b/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00010.png index 06704db..139058c 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00010.png 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 index 2737bf9..dc3f263 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00011.png 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 index 17ff048..dd49ec2 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00012.png 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 index 3a16119..7623766 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00013.png 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 index 3a16119..0562b8b 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_create_stake_pool/00014.png 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/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/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/00010.png b/tests/snapshots/nanosp/test_sign_tx_htlc/00010.png index b168952..40b1181 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_htlc/00010.png 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 index 3a16119..f113d41 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_htlc/00011.png 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 index b2e3594..195e6f3 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_htlc/00012.png 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/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/00010.png b/tests/snapshots/nanosp/test_sign_tx_issue_nft/00010.png index af149c9..84ff3f7 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00010.png 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 index 4336cee..3fdec7f 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00011.png 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 index 3a16119..a9bd3e2 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00012.png 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 index 3a16119..b9a3aba 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_issue_nft/00013.png 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/00001.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00001.png index a7b61f1..7a9b805 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00001.png 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 index c31d61b..342974f 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00002.png 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 index 291da46..a8a6913 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00003.png 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 index 2737bf9..11e1d3f 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00004.png 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 index 62b8f91..2737bf9 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00005.png 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 index 3a16119..b00f750 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00006.png 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/00008.png b/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00008.png deleted file mode 100644 index f265d69..0000000 Binary files a/tests/snapshots/nanosp/test_sign_tx_lock_then_transfer/00008.png and /dev/null 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_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/00010.png b/tests/snapshots/nanosp/test_sign_tx_order_conclude/00010.png index b2e3594..4738c2b 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_order_conclude/00010.png 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/00010.png b/tests/snapshots/nanosp/test_sign_tx_order_fill/00010.png index b2e3594..a6a6827 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_order_fill/00010.png 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 index b2e3594..315c395 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_order_fill/00011.png 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_transfer/00001.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00001.png index 192c2bd..75337cb 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_transfer/00001.png 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 index 75337cb..0378fc6 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_transfer/00002.png 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 index 0378fc6..11e1d3f 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_transfer/00003.png and b/tests/snapshots/nanosp/test_sign_tx_transfer/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00005.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00005.png index 6e3cb60..7898c99 100644 Binary files a/tests/snapshots/nanosp/test_sign_tx_transfer/00005.png and b/tests/snapshots/nanosp/test_sign_tx_transfer/00005.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_transfer/00007.png b/tests/snapshots/nanosp/test_sign_tx_transfer/00007.png deleted file mode 100644 index 3a16119..0000000 Binary files a/tests/snapshots/nanosp/test_sign_tx_transfer/00007.png and /dev/null 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/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/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/00001.png b/tests/snapshots/nanox/test_app_mainmenu/00001.png index bdbc0ff..77bcafd 100644 Binary files a/tests/snapshots/nanox/test_app_mainmenu/00001.png and b/tests/snapshots/nanox/test_app_mainmenu/00001.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/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/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/00010.png b/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00010.png index 06704db..139058c 100644 Binary files a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00010.png 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 index 2737bf9..dc3f263 100644 Binary files a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00011.png 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 index 17ff048..dd49ec2 100644 Binary files a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00012.png 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 index 3a16119..7623766 100644 Binary files a/tests/snapshots/nanox/test_sign_tx_create_stake_pool/00013.png 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/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/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/00010.png b/tests/snapshots/nanox/test_sign_tx_htlc/00010.png index b168952..40b1181 100644 Binary files a/tests/snapshots/nanox/test_sign_tx_htlc/00010.png 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 index 3a16119..f113d41 100644 Binary files a/tests/snapshots/nanox/test_sign_tx_htlc/00011.png 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/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/00010.png b/tests/snapshots/nanox/test_sign_tx_issue_nft/00010.png index af149c9..84ff3f7 100644 Binary files a/tests/snapshots/nanox/test_sign_tx_issue_nft/00010.png 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 index 4336cee..3fdec7f 100644 Binary files a/tests/snapshots/nanox/test_sign_tx_issue_nft/00011.png 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 index 3a16119..a9bd3e2 100644 Binary files a/tests/snapshots/nanox/test_sign_tx_issue_nft/00012.png 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/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_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/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/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_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/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/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 index d755792..a08dbb1 100644 Binary files a/tests/snapshots/stax/test_app_mainmenu/00000.png 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 index 381d216..79a7cdf 100644 Binary files a/tests/snapshots/stax/test_app_mainmenu/00001.png and b/tests/snapshots/stax/test_app_mainmenu/00001.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 index d755792..a08dbb1 100644 Binary files a/tests/snapshots/stax/test_get_public_key_confirm_accepted/00003.png and b/tests/snapshots/stax/test_get_public_key_confirm_accepted/00003.png differ diff --git a/tests/snapshots/stax/test_sign_message/00004.png b/tests/snapshots/stax/test_sign_message/00004.png index d755792..a08dbb1 100644 Binary files a/tests/snapshots/stax/test_sign_message/00004.png and b/tests/snapshots/stax/test_sign_message/00004.png differ diff --git a/tests/snapshots/stax/test_sign_message_pkh/00004.png b/tests/snapshots/stax/test_sign_message_pkh/00004.png index d755792..a08dbb1 100644 Binary files a/tests/snapshots/stax/test_sign_message_pkh/00004.png and b/tests/snapshots/stax/test_sign_message_pkh/00004.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 index 15da40f..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_change_token_authority/00000.png 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/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 index 15da40f..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_change_token_metadata_uri/00000.png 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/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 index ea44baa..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_create_delegation/00000.png and b/tests/snapshots/stax/test_sign_tx_create_delegation/00000.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 index ea44baa..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_create_stake_pool/00000.png 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/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 index 15da40f..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_delegation_staking/00000.png and b/tests/snapshots/stax/test_sign_tx_delegation_staking/00000.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 index 15da40f..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_freeze_tokens/00000.png and b/tests/snapshots/stax/test_sign_tx_freeze_tokens/00000.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 index ea44baa..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_htlc/00000.png and b/tests/snapshots/stax/test_sign_tx_htlc/00000.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 index ea44baa..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_issue_fungible_token/00000.png 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/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 index ea44baa..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_issue_nft/00000.png and b/tests/snapshots/stax/test_sign_tx_issue_nft/00000.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 index ea44baa..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00000.png 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/00010.png b/tests/snapshots/stax/test_sign_tx_lock_then_transfer/00010.png new file mode 100644 index 0000000..3b07cf0 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..3b07cf0 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_mint_tokens/00000.png b/tests/snapshots/stax/test_sign_tx_mint_tokens/00000.png index ea44baa..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_mint_tokens/00000.png and b/tests/snapshots/stax/test_sign_tx_mint_tokens/00000.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 index 3c0339b..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_order_conclude/00000.png and b/tests/snapshots/stax/test_sign_tx_order_conclude/00000.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 index 3c0339b..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_order_fill/00000.png and b/tests/snapshots/stax/test_sign_tx_order_fill/00000.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_transfer/00000.png b/tests/snapshots/stax/test_sign_tx_transfer/00000.png index 15da40f..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_transfer/00000.png and b/tests/snapshots/stax/test_sign_tx_transfer/00000.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 index 15da40f..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00000.png and b/tests/snapshots/stax/test_sign_tx_unfreeze_tokens/00000.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 index ea44baa..a46449f 100644 Binary files a/tests/snapshots/stax/test_sign_tx_unmint_tokens/00000.png and b/tests/snapshots/stax/test_sign_tx_unmint_tokens/00000.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 index 8103dcd..bfc8f09 100644 --- a/tests/test_app_mainmenu.py +++ b/tests/test_app_mainmenu.py @@ -7,16 +7,8 @@ def test_app_mainmenu(device, navigator, test_name): # Navigate in the main menu if device.is_nano: - instructions = [ - NavInsID.RIGHT_CLICK, - NavInsID.RIGHT_CLICK, - NavInsID.RIGHT_CLICK - ] + instructions = [NavInsID.RIGHT_CLICK] else: - instructions = [ - NavInsID.USE_CASE_HOME_SETTINGS, - NavInsID.USE_CASE_SUB_SETTINGS_NEXT, - NavInsID.USE_CASE_SUB_SETTINGS_EXIT - ] + 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 index 7b3dbcb..f9d10a5 100644 --- a/tests/test_error_cmd.py +++ b/tests/test_error_cmd.py @@ -3,7 +3,7 @@ from ragger.error import ExceptionRAPDU from application_client import MAINNET -from application_client.mintlayer_command_sender import (CLA, P1, P2, Errors, +from application_client.mintlayer_command_sender import (CLA, GetAppAndVersionP1, SignTxP1, P2, Errors, InsType) tx_metadata_obj = scalecodec.base.RuntimeConfiguration().create_scale_object("TxMetadataReq") @@ -28,18 +28,18 @@ def test_wrong_p1p2(backend): # Wrong P2 with pytest.raises(ExceptionRAPDU) as e: backend.exchange( - cla=CLA, ins=InsType.GET_PUBLIC_KEY, p1=P1.P1_START, p2=123 + 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=P1.P1_START, p2=P2.P2_MORE + 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=P1.P1_START + 1, p2=P2.P2_MORE + cla=CLA, ins=InsType.GET_PUBLIC_KEY, p1=GetAppAndVersionP1.P1_START + 1, p2=P2.P2_MORE ) assert e.value.status == Errors.SW_WRONG_P1P2 @@ -62,7 +62,7 @@ def test_invalid_state(backend): backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_TX_INPUT, # Try to continue a flow instead of start a new one + 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 @@ -75,9 +75,12 @@ def test_sign_tx_invalid_coin(backend, scenario_navigator, device, navigator): metadata = tx_metadata_obj.encode( { "coin": invalid_coin, - "version": 1, - "num_inputs": num_inputs, - "num_outputs": num_outputs, + "version": { + "V1": { + "num_inputs": num_inputs, + "num_outputs": num_outputs, + }, + }, } ).data @@ -85,7 +88,7 @@ def test_sign_tx_invalid_coin(backend, scenario_navigator, device, navigator): res = backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_START, + p1=SignTxP1.P1_START, p2=P2.P2_LAST, data=bytes(metadata), ) @@ -93,26 +96,29 @@ def test_sign_tx_invalid_coin(backend, scenario_navigator, device, navigator): assert e.value.status == Errors.SW_DESERIALIZE_FAIL -def test_sign_tx_invalid_P2_for_input(backend, scenario_navigator, device, navigator): +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 P1/P2 + expect an error for wrong context """ num_inputs = 2 num_outputs = 2 metadata = tx_metadata_obj.encode( { "coin": MAINNET, - "version": 1, - "num_inputs": num_inputs, - "num_outputs": num_outputs, + "version": { + "V1": { + "num_inputs": num_inputs, + "num_outputs": num_outputs, + }, + }, } ).data res = backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_START, + p1=SignTxP1.P1_START, p2=P2.P2_LAST, data=bytes(metadata), ) @@ -123,7 +129,7 @@ def test_sign_tx_invalid_P2_for_input(backend, scenario_navigator, device, navig res = backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_TX_OUTPUT, + p1=SignTxP1.P1_NEXT, p2=P2.P2_LAST, data=sign_tx_req_obj.encode( { @@ -142,7 +148,7 @@ def test_sign_tx_invalid_P2_for_input(backend, scenario_navigator, device, navig } ).data, ) - assert e.value.status == Errors.SW_WRONG_P1P2 + assert e.value.status == Errors.SW_WRONG_CONTEXT def test_sign_tx_invalid_input(backend, scenario_navigator, device, navigator): @@ -151,16 +157,19 @@ def test_sign_tx_invalid_input(backend, scenario_navigator, device, navigator): metadata = tx_metadata_obj.encode( { "coin": MAINNET, - "version": 1, - "num_inputs": num_inputs, - "num_outputs": num_outputs, + "version": { + "V1": { + "num_inputs": num_inputs, + "num_outputs": num_outputs, + }, + }, } ).data res = backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_START, + p1=SignTxP1.P1_START, p2=P2.P2_LAST, data=bytes(metadata), ) @@ -172,7 +181,7 @@ def test_sign_tx_invalid_input(backend, scenario_navigator, device, navigator): res = backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_TX_INPUT, + p1=SignTxP1.P1_NEXT, p2=P2.P2_LAST, data=bytes([0] * 10), ) @@ -186,16 +195,19 @@ def test_sign_tx_too_large_data(backend, scenario_navigator, device, navigator): metadata = tx_metadata_obj.encode( { "coin": MAINNET, - "version": 1, - "num_inputs": num_inputs, - "num_outputs": num_outputs, + "version": { + "V1": { + "num_inputs": num_inputs, + "num_outputs": num_outputs, + }, + }, } ).data res = backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_START, + p1=SignTxP1.P1_START, p2=P2.P2_LAST, data=bytes(metadata), ) @@ -207,7 +219,7 @@ def test_sign_tx_too_large_data(backend, scenario_navigator, device, navigator): res = backend.exchange( cla=CLA, ins=InsType.SIGN_TX, - p1=P1.P1_TX_INPUT, + p1=SignTxP1.P1_NEXT, p2=P2.P2_MORE, data=b"big_input_data", ) diff --git a/tests/test_name_version.py b/tests/test_name_version.py index 8ff22f9..f822470 100644 --- a/tests/test_name_version.py +++ b/tests/test_name_version.py @@ -12,5 +12,5 @@ def test_get_app_and_version(backend, backend_name): # 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 == "app" - assert version == "1.33.7" + assert app_name == "Mintlayer" + assert version == "0.1.0" diff --git a/tests/test_pubkey_cmd.py b/tests/test_pubkey_cmd.py index eccfc93..377aab8 100644 --- a/tests/test_pubkey_cmd.py +++ b/tests/test_pubkey_cmd.py @@ -1,14 +1,12 @@ import pytest from ragger.bip import CurveChoice, calculate_public_key_and_chaincode from ragger.error import ExceptionRAPDU -from ragger.navigator import NavIns, NavInsID 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 -from utils import ROOT_SCREENSHOT_PATH MNEMONIC = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" diff --git a/tests/test_sign_cmd.py b/tests/test_sign_cmd.py index aa36c2f..34adc6c 100644 --- a/tests/test_sign_cmd.py +++ b/tests/test_sign_cmd.py @@ -1,19 +1,15 @@ import pytest import scalecodec -from ragger.error import ExceptionRAPDU from ragger.navigator import NavIns, NavInsID -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, unpack_sign_tx_response) +from application_client import MAINNET +from application_client.mintlayer_command_sender import MintlayerCommandSender, sign_tx_review +from application_client.mintlayer_response_unpacker import unpack_get_public_key_response from application_client.mintlayer_transaction import Transaction -from utils import ROOT_SCREENSHOT_PATH, check_signature_validity sign_tx_req_obj = scalecodec.base.RuntimeConfiguration().create_scale_object("SignTxReq") -TX_RESPONSE_SIZE = 67 +TX_RESPONSE_SIZE = 71 def test_sign_tx_transfer(backend, scenario_navigator, device, navigator): @@ -90,29 +86,7 @@ def test_sign_tx_transfer(backend, scenario_navigator, device, navigator): coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] ) - # Enable display of transaction memo (NBGL devices only) - if not device.is_nano: - navigator.navigate( - [ - NavInsID.USE_CASE_HOME_SETTINGS, - NavIns(NavInsID.TOUCH, (200, 113)), - NavInsID.USE_CASE_SUB_SETTINGS_EXIT, - ], - screen_change_before_first_instruction=False, - screen_change_after_last_instruction=False, - ) - - # Send the sign device instruction. - # As it requires on-screen validation, the function is asynchronous. - # It will yield the result when the navigation is done - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation appropriate for this device - scenario_navigator.review_approve(custom_screen_text=r"Sign\stransfer") - - # The device as yielded the result, parse it and ensure that the signature is correct - response = client.get_async_response().data - - assert len(response) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=False, review_custom_screen_text=r"Sign\stransfer") def test_sign_tx_lock_then_transfer(backend, scenario_navigator, device, navigator): @@ -168,29 +142,7 @@ def test_sign_tx_lock_then_transfer(backend, scenario_navigator, device, navigat coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] ) - # Enable display of transaction memo (NBGL devices only) - if not device.is_nano: - navigator.navigate( - [ - NavInsID.USE_CASE_HOME_SETTINGS, - NavIns(NavInsID.TOUCH, (200, 113)), - NavInsID.USE_CASE_SUB_SETTINGS_EXIT, - ], - screen_change_before_first_instruction=False, - screen_change_after_last_instruction=False, - ) - - # Send the sign device instruction. - # As it requires on-screen validation, the function is asynchronous. - # It will yield the result when the navigation is done - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation appropriate for this device - scenario_navigator.review_approve(custom_screen_text=r"Sign\swithdrawal") - - # The device as yielded the result, parse it and ensure that the signature is correct - response = client.get_async_response().data - - assert len(response) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=True, review_custom_screen_text=r"Sign\swithdrawal") def test_sign_tx_create_delegation(backend, scenario_navigator, device, navigator): @@ -260,30 +212,7 @@ def test_sign_tx_create_delegation(backend, scenario_navigator, device, navigato coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] ) - # Enable display of transaction memo (NBGL devices only) - if not device.is_nano: - navigator.navigate( - [ - NavInsID.USE_CASE_HOME_SETTINGS, - NavIns(NavInsID.TOUCH, (200, 113)), - NavInsID.USE_CASE_SUB_SETTINGS_EXIT, - ], - screen_change_before_first_instruction=False, - screen_change_after_last_instruction=False, - ) - - print("create delegation test") - # Send the sign device instruction. - # As it requires on-screen validation, the function is asynchronous. - # It will yield the result when the navigation is done - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation appropriate for this device - scenario_navigator.review_approve(custom_screen_text=r"Sign\screate") - - # The device as yielded the result, parse it and ensure that the signature is correct - response = client.get_async_response().data - - assert len(response) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=False, review_custom_screen_text=r"Sign\screate") def test_sign_tx_delegation_staking(backend, scenario_navigator, device, navigator): @@ -346,29 +275,7 @@ def test_sign_tx_delegation_staking(backend, scenario_navigator, device, navigat coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] ) - # Enable display of transaction memo (NBGL devices only) - if not device.is_nano: - navigator.navigate( - [ - NavInsID.USE_CASE_HOME_SETTINGS, - NavIns(NavInsID.TOUCH, (200, 113)), - NavInsID.USE_CASE_SUB_SETTINGS_EXIT, - ], - screen_change_before_first_instruction=False, - screen_change_after_last_instruction=False, - ) - - # Send the sign device instruction. - # As it requires on-screen validation, the function is asynchronous. - # It will yield the result when the navigation is done - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation appropriate for this device - scenario_navigator.review_approve(custom_screen_text=r"Sign\sstake") - - # The device as yielded the result, parse it and ensure that the signature is correct - response = client.get_async_response().data - - assert len(response) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=False, review_custom_screen_text=r"Sign\sstake") def test_sign_tx_create_stake_pool(backend, scenario_navigator, device, navigator): @@ -452,29 +359,7 @@ def test_sign_tx_create_stake_pool(backend, scenario_navigator, device, navigato coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] ) - # Enable display of transaction memo (NBGL devices only) - if not device.is_nano: - navigator.navigate( - [ - NavInsID.USE_CASE_HOME_SETTINGS, - NavIns(NavInsID.TOUCH, (200, 113)), - NavInsID.USE_CASE_SUB_SETTINGS_EXIT, - ], - screen_change_before_first_instruction=False, - screen_change_after_last_instruction=False, - ) - - # Send the sign device instruction. - # As it requires on-screen validation, the function is asynchronous. - # It will yield the result when the navigation is done - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation appropriate for this device - scenario_navigator.review_approve(custom_screen_text=r"Sign\screate\sstake") - - # The device as yielded the result, parse it and ensure that the signature is correct - response = client.get_async_response().data - - assert len(response) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=False, review_custom_screen_text=r"Sign\screate\sstake") def test_sign_tx_issue_fungible_token(backend, scenario_navigator, device, navigator): @@ -551,14 +436,7 @@ def test_sign_tx_issue_fungible_token(backend, scenario_navigator, device, navig coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] ) - # Send the sign device instruction - with client.sign_tx(transaction=transaction): - # Validate the on-screen request - scenario_navigator.review_approve(custom_screen_text=r"Sign\screate\sToken") - - # The device has yielded the result, parse it and ensure that the signature is correct - response = client.get_async_response().data - assert len(response) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=False, review_custom_screen_text=r"Sign\screate\stoken") def test_sign_tx_issue_nft(backend, scenario_navigator, device, navigator): @@ -651,14 +529,7 @@ def test_sign_tx_issue_nft(backend, scenario_navigator, device, navigator): coin=MAINNET, inputs=[inp], input_commitments=[inp_commitment], outputs=[output] ) - # Send the sign device instruction - with client.sign_tx(transaction=transaction): - # Validate the on-screen request - scenario_navigator.review_approve(custom_screen_text=r"Sign\screate\sNFT") - - # The device has yielded the result, parse it and ensure that the signature is correct - response = client.get_async_response().data - assert len(response) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=False, review_custom_screen_text=r"Sign\screate\sNFT") def test_sign_tx_mint_tokens(backend, scenario_navigator, device, navigator): @@ -761,20 +632,7 @@ def test_sign_tx_mint_tokens(backend, scenario_navigator, device, navigator): outputs=[mint_output], ) - # Send the sign transaction instruction. - # It will yield the result when the user validates on-screen. - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation - scenario_navigator.review_approve(custom_screen_text=r"Sign\smint\sTokens") - # The device has yielded the result, parse it and ensure the signatures are correct - responses = client.get_all_signatures(transaction) - - # The device should have returned two signatures, one for each input that - # required signing (the Utxo and the AccountCommand). - # Each signature is 64 bytes + 3 sighash byte = 67 bytes. - assert len(responses) == 2 - for resp in responses: - assert len(resp) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=True, review_custom_screen_text=r"Sign\smint\stokens") def test_sign_tx_unmint_tokens(backend, scenario_navigator, device, navigator): @@ -911,20 +769,7 @@ def test_sign_tx_unmint_tokens(backend, scenario_navigator, device, navigator): outputs=[change_output], ) - # Send the sign transaction instruction. - # It will yield the result when the user validates on-screen. - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation - scenario_navigator.review_approve(custom_screen_text=r"Sign\sunmint\sTokens") - # The device has yielded the result, parse it and ensure the signatures are correct - responses = client.get_all_signatures(transaction) - - # The device should have returned two signatures, one for each input that - # required signing (the Utxo and the AccountCommand). - # Each signature is 64 bytes + 3 sighash byte = 67 bytes. - assert len(responses) == 3 - for resp in responses: - assert len(resp) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=True, review_custom_screen_text=r"Sign\sunmint\stokens") def test_sign_tx_freeze_tokens(backend, scenario_navigator, device, navigator): @@ -1023,20 +868,7 @@ def test_sign_tx_freeze_tokens(backend, scenario_navigator, device, navigator): outputs=[change_output], ) - # Send the sign transaction instruction. - # It will yield the result when the user validates on-screen. - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation - scenario_navigator.review_approve(custom_screen_text=r"Sign\sfreeze\sTokens") - # The device has yielded the result, parse it and ensure the signatures are correct - responses = client.get_all_signatures(transaction) - - # The device should have returned two signatures, one for each input that - # required signing (the Utxo and the AccountCommand). - # Each signature is 64 bytes + 3 sighash byte = 67 bytes. - assert len(responses) == 2 - for resp in responses: - assert len(resp) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=True, review_custom_screen_text=r"Sign\sfreeze\stokens") def test_sign_tx_unfreeze_tokens(backend, scenario_navigator, device, navigator): @@ -1135,20 +967,7 @@ def test_sign_tx_unfreeze_tokens(backend, scenario_navigator, device, navigator) outputs=[change_output], ) - # Send the sign transaction instruction. - # It will yield the result when the user validates on-screen. - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation - scenario_navigator.review_approve(custom_screen_text=r"Sign\sunfreeze") - # The device has yielded the result, parse it and ensure the signatures are correct - responses = client.get_all_signatures(transaction) - - # The device should have returned two signatures, one for each input that - # required signing (the Utxo and the AccountCommand). - # Each signature is 64 bytes + 3 sighash byte = 67 bytes. - assert len(responses) == 2 - for resp in responses: - assert len(resp) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=True, review_custom_screen_text=r"Sign\sunfreeze") def test_sign_tx_change_token_authority(backend, scenario_navigator, device, navigator): @@ -1256,20 +1075,7 @@ def test_sign_tx_change_token_authority(backend, scenario_navigator, device, nav outputs=[change_output], ) - # Send the sign transaction instruction. - # It will yield the result when the user validates on-screen. - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation - scenario_navigator.review_approve(custom_screen_text=r"Sign\schange\sToken") - # The device has yielded the result, parse it and ensure the signatures are correct - responses = client.get_all_signatures(transaction) - - # The device should have returned two signatures, one for each input that - # required signing (the Utxo and the AccountCommand). - # Each signature is 64 bytes + 3 sighash byte = 67 bytes. - assert len(responses) == 2 - for resp in responses: - assert len(resp) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=True, review_custom_screen_text=r"Sign\schange\stoken") def test_sign_tx_change_token_metadata_uri( @@ -1374,20 +1180,7 @@ def test_sign_tx_change_token_metadata_uri( outputs=[change_output], ) - # Send the sign transaction instruction. - # It will yield the result when the user validates on-screen. - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation - scenario_navigator.review_approve(custom_screen_text=r"Sign\schange\sToken") - # The device has yielded the result, parse it and ensure the signatures are correct - responses = client.get_all_signatures(transaction) - - # The device should have returned two signatures, one for each input that - # required signing (the Utxo and the AccountCommand). - # Each signature is 64 bytes + 3 sighash byte = 67 bytes. - assert len(responses) == 2 - for resp in responses: - assert len(resp) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=True, review_custom_screen_text=r"Sign\schange\stoken") def test_sign_tx_order_fill(backend, scenario_navigator, device, navigator): @@ -1528,20 +1321,7 @@ def test_sign_tx_order_fill(backend, scenario_navigator, device, navigator): outputs=[change_output, fill_output], ) - # Send the sign transaction instruction. - # It will yield the result when the user validates on-screen. - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation - scenario_navigator.review_approve(custom_screen_text=r"Sign\sfill\sOrder") - # The device has yielded the result, parse it and ensure the signatures are correct - responses = client.get_all_signatures(transaction) - - # The device should have returned two signatures, one for each input that - # required signing (the Utxo and the AccountCommand). - # Each signature is 64 bytes + 3 sighash byte = 67 bytes. - assert len(responses) == 2 - for resp in responses: - assert len(resp) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=True, review_custom_screen_text=r"Sign\sfill\sorder") def test_sign_tx_order_conclude(backend, scenario_navigator, device, navigator): @@ -1677,20 +1457,7 @@ def test_sign_tx_order_conclude(backend, scenario_navigator, device, navigator): outputs=[change_output, conclude_output], ) - # Send the sign transaction instruction. - # It will yield the result when the user validates on-screen. - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation - scenario_navigator.review_approve(custom_screen_text=r"Sign\sconclude\sOrder") - # The device has yielded the result, parse it and ensure the signatures are correct - responses = client.get_all_signatures(transaction) - - # The device should have returned two signatures, one for each input that - # required signing (the Utxo and the AccountCommand). - # Each signature is 64 bytes + 3 sighash byte = 67 bytes. - assert len(responses) == 2 - for resp in responses: - assert len(resp) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=True, review_custom_screen_text=r"Sign\sconclude\sorder") def test_sign_tx_htlc(backend, scenario_navigator, device, navigator): @@ -1796,16 +1563,4 @@ def test_sign_tx_htlc(backend, scenario_navigator, device, navigator): outputs=[htlc_output, change_output], ) - # Send the sign transaction instruction. - # It will yield the result when the user validates on-screen. - with client.sign_tx(transaction=transaction): - # Validate the on-screen request by performing the navigation - scenario_navigator.review_approve(custom_screen_text=r"Sign\screate\sHTLC") - # The device has yielded the result, parse it and ensure the signatures are correct - responses = client.get_all_signatures(transaction) - - # The device should have returned one signature - # Each signature is 64 bytes + 3 sighash byte = 67 bytes. - assert len(responses) == 1 - for resp in responses: - assert len(resp) == TX_RESPONSE_SIZE + sign_tx_review(client, device, navigator, scenario_navigator, transaction, has_command_input=False, review_custom_screen_text=r"Sign\screate\sHTLC") diff --git a/tests/test_sign_message.py b/tests/test_sign_message.py index c3d2995..f14ae97 100644 --- a/tests/test_sign_message.py +++ b/tests/test_sign_message.py @@ -1,17 +1,10 @@ import pytest import scalecodec # type: ignore -from ragger.bip import CurveChoice, calculate_public_key_and_chaincode from ragger.error import ExceptionRAPDU -from ragger.navigator import NavIns, NavInsID 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 -from utils import ROOT_SCREENSHOT_PATH - -MNEMONIC = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" # In this test we check that the message signing works @@ -23,8 +16,9 @@ def test_sign_message(backend, scenario_navigator): scenario_navigator.review_approve() response = scalecodec.base.ScaleBytes(client.get_async_response().data) - msg_signature_obj = scalecodec.base.RuntimeConfiguration().create_scale_object("MsgSignature", data=response) - sig = msg_signature_obj.decode() + response_obj = scalecodec.base.RuntimeConfiguration().create_scale_object("Response", data=response) + response = response_obj.decode() + assert response["MessageSignature"] is not None def test_sign_message_pkh(backend, scenario_navigator): path = "m/44'/19788'/0'/0/0" @@ -34,8 +28,9 @@ def test_sign_message_pkh(backend, scenario_navigator): scenario_navigator.review_approve() response = scalecodec.base.ScaleBytes(client.get_async_response().data) - msg_signature_obj = scalecodec.base.RuntimeConfiguration().create_scale_object("MsgSignature", data=response) - sig = msg_signature_obj.decode() + response_obj = scalecodec.base.RuntimeConfiguration().create_scale_object("Response", data=response) + response = response_obj.decode() + assert response["MessageSignature"] is not None # Message signing refused test