Address QR: show and scan a plain SS58 string, not polkadot-js's payload #9

Open
opened 2026-09-15 08:22:54 +00:00 by grenade · 0 comments
Owner

Split out of #5, which wrongly lumped this in with air-gapped signing (#10). This one has no protocol problem at all and is worth keeping.

Why it matters

Getting an address from the desktop extension onto a phone. There is no good alternative — a Quantus address is 49 characters of base58 and retyping it is exactly the operation nobody should be doing by hand.

The Quantus mobile app already has both ends of this:

  • shows an address as a QR — quantus_sdk/lib/src/ui/components/quantus_qr.dart, reached from the receive screen
  • scans one — mobile-app/lib/v2/components/qr_scanner_page.dart, reached from send → select recipient and from swap

The format is a bare address

QrImageView(data: accountId, )          // shows
final code = capture.barcodes.firstOrNull?.rawValue;   // scans, then validates

No envelope, no prefix, no genesis hash. So the extension must render the raw SS58 string.

What it must not use is polkadot-js's QrDisplayAddress, which wraps it:

createAddressPayload(address, genesisHash)  `substrate:${address}:${genesisHash}`

A phone scanning that gets a string its validator rejects — or, worse, something that passes a loose validator and is not an address. The component is the wrong one; a plain QR of pair.address is the right one.

Scope

  • Show: a QR of the account's SS58 address, wherever the address is already displayed for copying.
  • Scan: the reverse, for recipient entry, if the extension grows a send flow. Lower priority — it depends on there being somewhere to type a recipient, which the extension does not have today.

Check before settling the format

The mobile scanner also accepts a /pay deep link — its _handleCode bounds length and comments that "everything scanned here is an address or a /pay link". If that carries an amount or a reference, an extension showing a payment request rather than a bare address may be the more useful thing, and the two should at least not conflict. Worth reading that format before fixing ours.

Also worth matching: the mobile QR embeds a Quantus logo and uses error-correction level M. Cosmetic, but a QR that looks like the one in the other app is easier to trust.

Acceptance

  • the Quantus mobile app's scanner reads an address QR from the extension and fills a recipient field with it
  • the rendered payload is exactly the SS58 string, with no prefix or envelope
  • it renders at prefix 189
Split out of #5, which wrongly lumped this in with air-gapped signing (#10). This one has no protocol problem at all and is worth keeping. ## Why it matters Getting an address from the desktop extension onto a phone. There is no good alternative — a Quantus address is 49 characters of base58 and retyping it is exactly the operation nobody should be doing by hand. The Quantus mobile app already has both ends of this: - **shows** an address as a QR — `quantus_sdk/lib/src/ui/components/quantus_qr.dart`, reached from the receive screen - **scans** one — `mobile-app/lib/v2/components/qr_scanner_page.dart`, reached from **send → select recipient** and from **swap** ## The format is a bare address ```dart QrImageView(data: accountId, …) // shows final code = capture.barcodes.firstOrNull?.rawValue; // scans, then validates ``` No envelope, no prefix, no genesis hash. So the extension must render the **raw SS58 string**. What it must **not** use is polkadot-js's `QrDisplayAddress`, which wraps it: ```js createAddressPayload(address, genesisHash) → `substrate:${address}:${genesisHash}` ``` A phone scanning that gets a string its validator rejects — or, worse, something that passes a loose validator and is not an address. The component is the wrong one; a plain QR of `pair.address` is the right one. ## Scope - **Show**: a QR of the account's SS58 address, wherever the address is already displayed for copying. - **Scan**: the reverse, for recipient entry, if the extension grows a send flow. Lower priority — it depends on there being somewhere to type a recipient, which the extension does not have today. ## Check before settling the format The mobile scanner also accepts a `/pay` deep link — its `_handleCode` bounds length and comments that "everything scanned here is an address or a /pay link". If that carries an amount or a reference, an extension showing a *payment request* rather than a bare address may be the more useful thing, and the two should at least not conflict. Worth reading that format before fixing ours. Also worth matching: the mobile QR embeds a Quantus logo and uses error-correction level M. Cosmetic, but a QR that looks like the one in the other app is easier to trust. ## Acceptance - [ ] the Quantus mobile app's scanner reads an address QR from the extension and fills a recipient field with it - [ ] the rendered payload is exactly the SS58 string, with no prefix or envelope - [ ] it renders at prefix 189
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: quantus/extension#9