Skip to content

Latest commit

 

History

History
78 lines (50 loc) · 6.55 KB

File metadata and controls

78 lines (50 loc) · 6.55 KB

Solution: LP-0010 — Shell dApp Integration Proof of Concept

Submitted by: mmlado

Summary

A web dApp that integrates with the Shell hardware wallet entirely via QR codes — no browser extension, no USB, no Bluetooth. It connects by scanning Shell's export QR, displays derived addresses across all supported derivation paths, and completes a full sign/verify round-trip for both Ethereum and Bitcoin messages. Outbound sign requests now support animated multi-part URs for longer messages, and the Bitcoin response is verified in-browser against the requested message and address before the UI marks it as valid. Confirmed working end-to-end on a real Shell device.

Repository

Approach

The dApp speaks ERC-4527 — a QR-based airgapped signer protocol built on Uniform Resources (UR) and CBOR — directly, without the Keystone SDK.

All protocol logic lives in src/lib/, a framework-agnostic library structured for future npm extraction. Key design decisions:

  • UR decoding and encoding: a single URDecoder instance persists across camera frames to support animated multi-part QRs from Shell, and outbound sign requests are emitted as animated UR sequences when the payload is too large for one frame. The scanner returns false to keep running on parse errors so a bad frame doesn't kill the session.
  • CBOR: cborg is used for decoding (browser-safe, no Node.js Buffer). For encoding sign requests, a minimal custom encoder (cbor.ts) handles CBOR tags — something no browser-compatible encoder supported out of the box.
  • source-fingerprint: Shell validates that the fingerprint in every sign request's keypath matches the inserted card. parseXpub extracts it from the scanned UR; both sign request builders include it automatically.
  • Browser-safe Bitcoin verification: the dApp verifies Shell's Bitcoin signature response locally using the returned compressed public key, the requested address, and the signed message. bip322-js is kept in test-only coverage to prove compatibility, but is not bundled into the browser runtime.
  • Key type detection: purpose and coinType from the origin keypath determine which address type to derive. Only key types present in the scanned UR are shown as active in the UI.

Success Criteria Checklist

  • Connects to Shell via QRURDecoder handles both single-frame and animated multi-part QR codes. No browser extension, native app, or network connection required.
  • Displays addresses and public keys across derivation paths — the UI lists all four key types: EVM (m/44'/60'/0'/0/0), Bitcoin legacy P2PKH (m/44'/0'/0'/0/0), nested SegWit P2SH-P2WPKH (m/49'/0'/0'/0/0), and native SegWit P2WPKH (m/84'/0'/0'/0/0). Because a single Shell export QR contains either an Ethereum key or Bitcoin keys — not both simultaneously — only the address types present in the scanned UR are active; the rest are greyed out.
  • Message signing with full QR round-trip — EVM uses EIP-191 personal_sign (ur:eth-sign-request data-type 3, ur:eth-signature response). Bitcoin uses ur:btc-sign-request (data-type 1, btc-message) with ur:btc-signature response. Long sign requests are emitted as animated outbound UR sequences when needed, and the Bitcoin response is verified in-browser before the UI marks it as valid. Both confirmed working on device.
  • Fully airgapped — all data exchange happens through QR codes. No network requests are made after the page loads.
  • Developer integration guide and Apache-2.0 license — see docs/integration-guide.md.

FURPS Self-Assessment

Functionality

Supports all four derivation paths. EVM signing (EIP-191) and Bitcoin message signing are both confirmed working end-to-end against a real Shell device. Outbound sign requests support animated multipart URs, and the Bitcoin signature response is verified locally before the app displays a success state.

The protocol library (src/lib/) is framework-agnostic and structured for extraction as an npm package. It handles both ur:crypto-hdkey (single key) and ur:crypto-account (multi-key) connection QRs.

Usability

  • Scan Shell's QR → addresses appear immediately, first available key is auto-selected
  • Clicking a key row selects it (highlighted); inactive keys are visually greyed out
  • Sign flow: type message → press Sign → QR appears (single-frame or animated multipart depending on payload size) → press "Scan Shell's signature" → camera replaces QR → scan Shell's response → signature displayed with a visible verified/failed status indicator
  • Supports light and dark theme via prefers-color-scheme

Reliability

  • Animated QR support: a single URDecoder instance persists across frames so all inbound parts are accumulated correctly, and outbound sign requests cycle through all UR fragments until scanned
  • Scanner keeps running on parse errors — a bad frame or unrecognised QR doesn't kill the session
  • Bitcoin responses are checked against both the signed message and the expected address before the UI marks them as verified
  • 56 unit tests covering: CBOR encoder (all branches), address derivation (P2PKH, P2WPKH, P2SH-P2WPKH, EIP-55), xpub parsing (UR and raw base58), key derivation, eth-sign-request structure, btc-sign-request structure, multipart outbound UR generation, browser-safe Bitcoin verification, and BIP-322 compatibility in test-only coverage

Performance

Single-page app, no backend. The production bundle remains browser-safe and no longer pulls bip322-js into the client runtime. Address derivation, signature verification, and QR encoding are instantaneous on modern hardware.

Supportability

npm test          # 56 tests via Vitest
npm run lint      # ESLint (0 errors)
npx prettier --check "src/**/*.{ts,tsx}"
npm run build     # production build

All library code lives in src/lib/ with no React dependency, making it straightforward to extract. Each module has a single clear responsibility. See docs/integration-guide.md for a full developer walkthrough of the protocol.

Supporting Materials

  • docs/integration-guide.md — developer integration guide covering the full QR exchange format, connection flow, derivation paths, signing protocol, and CBOR implementation notes
  • Live demo

Terms & Conditions

By submitting this solution, I confirm that I have read and agree to the Terms & Conditions.