Skip to content

feat: introduce custody ledger - #400

Open
turbocrime wants to merge 21 commits into
mainfrom
introduce-custody-ledger
Open

feat: introduce custody ledger#400
turbocrime wants to merge 21 commits into
mainfrom
introduce-custody-ledger

Conversation

@turbocrime

@turbocrime turbocrime commented Jul 30, 2025

Copy link
Copy Markdown
Collaborator

Adds foundational support for Ledger devices including storage schema updates, wallet model changes, and testing infrastructure. Onboarding and other UI is in #402

Key Changes

  • Storage Schema: Added ledgerUsb custody type in v3 schema with v2→v3 migration
  • Wallet Model: Updated to handle multiple custody types and use Wallet.fromJson() instead of direct protobuf parsing
  • Testing: Added Ledger dependencies and Zemu emulator testing with visual snapshots
  • Chrome Mocking: Enhanced storage area mocks with change event listeners

Notes

  • Ledger testing uses zondax/ledger-penumbra cloned into a new directory rather than as a git submodule, as the makefiles require a .git directory that isn't present in submodules

Files Changed

  • packages/storage-chrome/src/versions/v3.ts - New custody type definition
  • packages/storage-chrome/src/migrations/local-v2-v3.ts - Migration logic
  • packages/wallet/package.json - Ledger testing dependencies and scripts
  • packages/mock-chrome/src/mocks/storage-area.ts - Storage change events
  • Various files - Replace fromJsonString with fromJson

@turbocrime turbocrime mentioned this pull request Jul 30, 2025
@turbocrime
turbocrime force-pushed the introduce-custody-ledger branch from 288e3df to 9c06259 Compare August 1, 2025 23:43
@turbocrime turbocrime changed the title Introduce custody ledger feat: introduce custody ledger Aug 1, 2025
@turbocrime
turbocrime force-pushed the introduce-custody-ledger branch from 9c06259 to 72aa29f Compare August 1, 2025 23:50
@turbocrime
turbocrime marked this pull request as ready for review August 16, 2025 12:06
@TalDerei
TalDerei self-requested a review August 28, 2025 19:08

@TalDerei TalDerei left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few nits, but otherwise the ledger support scaffolding looks great!

Comment on lines +27 to +30
// absent values now explicitly required
backupReminderSeen: undefined,
compactFrontierBlockHeight: undefined,
walletCreationBlockHeight: undefined,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: why the explicit requirement here?

Comment on lines +27 to +35
// lol
backupReminderSeen:
typeof old.backupReminderSeen === 'boolean' ? old.backupReminderSeen : undefined,
compactFrontierBlockHeight:
typeof old.compactFrontierBlockHeight === 'number'
? old.compactFrontierBlockHeight
: undefined,
walletCreationBlockHeight:
typeof old.walletCreationBlockHeight === 'number' ? old.walletCreationBlockHeight : undefined,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: can't we do without this?

Comment on lines +30 to +36
// check the device info
// const deviceInfo = await ledgerApp.deviceInfo();
// console.debug('deviceInfo', deviceInfo);

// check the app info
// const appInfo = await ledgerApp.appInfo();
// console.debug('appInfo', appInfo);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: remove

Comment on lines +29 to +31
// check the device info
// const deviceInfo = await ledgerApp.deviceInfo();
// console.debug('deviceInfo', deviceInfo);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: remove

produce((state: AllSlices) => {
state.network.chainId = stored
? AppParameters.fromJsonString(stored).chainId
? AppParameters.fromJson(stored).chainId

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: this caught my eye. v3 schema suggests that param is stored as a string, not a parsed object. let's revert this back to AppParameters.fromJsonString(stored).

Comment on lines +5 to +12
filter != null &&
device != null &&
filter.vendorId === device.vendorId &&
filter.productId === device.productId &&
filter.classCode === device.deviceClass &&
filter.subclassCode === device.deviceSubclass &&
filter.protocolCode === device.deviceProtocol &&
filter.serialNumber === device.serialNumber;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: this seems super strict, can we relax the matching conditions to only vendorId/productId/serialNumber?

> {
version(iv: FromV): ToV;
transform(fs: Partial<FromState>): ToState | Promise<ToState>;
transform(fs: Partial<FromState>): Explicit<ToState> | Promise<Explicit<ToState>>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: explicit flag here requires older migrations set optional keys to undefined to satisfy the type. don't know what the implication of that is, but i'd rather not change this. let's revert and remove absent values that are now explicitly required.

* @param passKey the correct key
* @throws Error if the key is incorrect
*/
protected async unseal(passKey: Key) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: doesn't matter. but let's mark this as private.

* @param to instance to which the implementations shall be bound
* @param unsealed decrypted data from the wallet's custody box
*/
export function bindCustodyImpl<T extends CustodyTypeName>(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: ack – glue layer that attaches to the right custody-specific impl.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants