Project: Zenon Ledger App

Zenon wallet application for Ledger Nano S/X/SP and Stax

Team: HyperCore-One
Repository: ledger-app-zenon
Proposal: Accelerator-Z

Project status

  • phase 1 - Unaudited developer mode release - PR #3
  • phase 2 - Developer mode release * (waiting for review)
  • phase 3 - Public release

*) The app submission has been accepted by Ledger and is waiting to be reviewed. You can track the progress of the embedded app from here Airtable - Integration Board BETA

Additional projects

  • Ledger Wallet for CLI (dart & .NET) - PR #43
  • Ledger Wallet for Syrius - PR #6
  • Pillar migration

See the AZ-proposal for more information on the additional projects.

1 Like

Much progress has been made with the implementation of the Zenon Ledger App. Zenon’s cryptographic security has been implemented and a first simulation trial to sign a transaction has been successful. It won’t be long before an on-chain trial can be done.

In this post, using checkboxes, I will periodically update the project’s progress on main tasks until it’s ready for publishing.

Transaction signature flow


  • Receive
  • Parsing
  • Selection
  • Display
  • Signing

Anatomy of a transaction

  • Loading the transaction data;
  • Presenting context with the transaction prompt;
  • Reviewing the transaction data;
  • Signing the transaction;
  • and rejecting the transaction.

High level overview of main tasks

  • Get in touch with the Ledger developer community
  • Learn and set up the BOLOS environment
  • Learn Ledger framework and SDKs
  • Set up repository according to Ledger security guidelines (CICD)
  • Design icons
  • Design UI flows
  • Define and implement APDUs
  • Implement transaction signature flow
  • Documentation
  • Functional tests

Did you manage to connect the Ledger App to Syrius?

No not yet. First everything wil be developed and tested via Speculos using functional tests, then when the transaction flow is fully implemented it will be tested on the physical devices. Testing through syrius just adds a layer of complexity. Better to make sure the app passes all functional tests before connecting it to Syrius.


I can help you with the Syrius integration.


I secretly assumed that :wink:

As stated in the proposal, the actual integration of Syrius falls outside the scope of this project. I will however run tests to make sure everything works properly on-chain using specific cli tools.

As for the Syrius integration, I think it’s better to look at the SDK first. The wallet of the SDK can be abstracted so that the implementation can be replaced with, for example, a Ledger Wallet implementation and others in the future.

Syrius will then simply use an abstract wallet interface and not even know which specific implementation is being used.

What do we think of the Zenon icon like this?

Unfortunately, as it is now designed, the icon cannot be placed in the middle. Other attempts where the icon can be placed in the middle do not work well on the slanted side of the Z.



looks good to me

1 Like

Concerning the sign transaction design UI flows.

Receive transactions

Unlike other cryptocurrencies, Zenon requires unreceived transactions to be signed. The proposal mentioned that the send flow is applicable for both transaction types. This is partially true, because unreceived transactions do not contain the same information. Therefore, the UI flow cannot show the amount and the from address. In order to show this information , a separate “from” transaction needs to be supplied.

The current implementation accepts one transaction for signing, namely the transaction to be signed. Future versions may extend this for unreceived transactions.

This means that the UI flow for signing receive transactions will be different, see below:

send tx = blocktype 2 & 4
receive tx = blocktype 1, 3 & 5

A send transaction has the following flow:

  1. Review transaction
  2. Type (display send)
  3. Amount (display amount and token symbol ZNN, QSR or ZTS)
  4. Address (display to zenon address)
  5. Approve or Refuse

A receive transaction has the following flow:

  1. Review transaction
  2. Type (display receive)
  3. Hash (display tx hash as hexidecimals)
  4. Approve or Refuse

Blind signing

The proposal also mentioned the following about blind signing.

Signing unreceived transactions or interacting with Embedded Smart Contracts will possibly require a blind signing setting.

It turns out that blind signing is not required for both mentioned types of transactions. However, it can be used to sign unknown data formats. For example, if the ledger app doesn’t recognise the send tx data, it will hash and display it for approval. The option could be useful if you want to sign something other than transactions.

In order to use the blind signing option it needs to be implemented and enabled by the user. This option is considered a could have and is not required for the first version.

Unattended signing

Unattended signing signs a transaction without any user (display) interaction. This is a bit controversial and while technically possible, I haven’t seen any implementations of it.

I’m currently considering this option as a won’t.

The app is functionally ready for the NanoS, NanoS Plus, NanoX and Stax. The code will be soon published, when it is cleaned up and documented.

The app supports two main commands, namely requesting the public key and signing a transaction.

Below an overview of the UI flow of the NanoS.

The app supports ZNN, QSR and ZTS*, bigint and decimals for displaying the amount.

*) ZTS decimals and symbol are not known and cannot displayed in version 1.0.0.

During the implementation, two future features were identified, namely providing the ledger with token info and the receive transaction info.

Token information command

The decimal precision and symbol of the ZNN and QSR coins are statically known, but the decimal precision and symbol of a ZTS token are not known in advance. Therefore, the current implementation cannot display decimal precision and the token symbol in the case of a ZTS token when signing a transaction.

Instead, the current implementation shows the amount without decimals and uses the ZTS symbol.

As a future enhancement, the app can include a token info command to supplement the token info. In the case of a ZTS token, the client will first provide the app with the token info by sending the token info command and then have the transaction signed.

The app checks and uses it if appropriate token information is present or falls back to the current implementation.

Transaction information command

Like the token-information command, additional transaction information can be provided in case of signing a receive transaction. The details of the receive transaction can be displayed in the same way as when signing a send transaction.

The app checks and uses it if appropriate transaction information is present or falls back on the current implementation (display hash).



The next steps are to implement the Syrius <-> Ledger connection, right?

For desktop via USB and for mobile I guess we’ll need a Bluetooth connection.


Thanks alienc0der.

I’ve got the app running on a NanoS. I also got a NanoX, but it turns out you need a developer edition to be able to upload custom apps to it in developer mode :angry:

I’m going to write a Flutter plugin for the app. This will allow us to easily setup comms with the device, then I think we have a good basis to start with Syrius implementation.

Mobile is also possible with an USB connection, but you need an USB-C to USB-A adapter. Both are supported.


Will there be a way to move pillars onto a Ledger at some point ? Is this even technically possible?

As mentioned in the proposal:

Pillar migration

Node operators have expressed the need to able to migrate their addresses. For complete support, node operators will need a way to move pillars from one address to another without dismantling them (and re-burning QSR, etc). Without this all existing pillars will forever stay in hot wallets.

We will do research in a migration feature for pillars in a separate project. Technically it’s possible, but at this stage we don’t know what implications such a feature will have, if any.

1 Like

The source code has been published to the develop branch of the ledger-app-zenon repo.

All checks pass except for APP_LOAD_PARAMS. The task fails because our token is not yet registered in the ledger-database repo. The registration progress is part of phase 2.

The desired app load params are:

"ZTS": {
  "appFlags": {"nanos": "0x000", "nanos2": "0x000", "nanox": "0x200", "stax": "0x200"},
  "appName": "Zenon",
  "curve": ["ed25519"],
  "path": ["44'/73404'"]

Efforts will be made to make a flutter plugin available for integration in Syrius and unit tests and fuzzing will be improved.

Version 1.0.0 will be released once the app has been thoroughly tested by the community.

Instructions for loading the app on a ledger device can be found in the readme. You need a special developer mode edition to upload the ledger app to a NanoX. The NanoS and NanoS Plus are unrestricted.

Identified future features:

  • SET_TOKEN command
  • SET_FROM_TX command
  • SIGN_TX_HASH command
  • Advanced mode
  • Display contract data

I wish I had a Ledger to test the app. Do you know if I can virtualize the hardware?

I see the fuzzing code in your repo. Nice!

The functional tests included in the repo contain tests with Speculor. The tests simulates all scenarios on all 4 ledger devices. The display results are captured with a golden run, and consequently used for comparing the resutls of the tests.

I’m pretty confident that the APDU’s communication works accordingly. The fuzzing tests will help to trackle some of the unexpected scenarios. The fuzzing code is not yet complete.


It is possible to change the backend of the functional tests with a physical device. I’ve managed to successfully run the functional tests on a Nano S. Not all tests will be able to run with success because some rely on ledger’s built-in seed phrase, causing the calculated public key to be different.

The function call in the tests tests/ needs to be called with a custom mnemonic in other for all tests to succeed.

custom_mnemonic = "[enter mnemonic here]"


To run the tests on a physical device, change line 90 of .vscode/tasks.json to:

"command": "docker exec -it ${config:container_name} bash -c 'pytest tests/ --tb=short -v --device ${input:model} --backend LedgerWallet'",

The physical device must be started, with the expected application installed and running, and connected to the computer through USB.


I have completed the flutter library for communicating with the ledger. All functions can be controlled using the sample application.

So far, I have only been able to test the library on Windows on a Nano S.

The library is still on my personal account for now. Feel free to fork and improve.

This library is all you need to complete the ledger implementation for Syrius.


Check out the Zenon Ledger Demo