Skip to content

recovery: find Xverse accounts at Xverse's Argent build (#734) - #763

Merged
derek-flossman merged 3 commits into
release/v0.10.8from
fix/734-xverse-class-hash
Oct 26, 2026
Merged

derek-flossman merged 3 commits into
release/v0.10.8from
fix/734-xverse-class-hash

Conversation

@derek-flossman

Copy link
Copy Markdown
Collaborator

Refs #734
Refs #727

Summary

Seed import now finds Starknet accounts made in Xverse after 2025-06-30.

Xverse derives keys on Bramble's own ladder (m/44'/9004'/{i}'/0/0, then grindKey) and deploys with salt = public key, deployer 0 and the Argent 0.4.0 constructor (Signer::Starknet(pubkey), guardian: None). Since 2025-06-30 it deploys at its own Argent build, 0x663fc01a…bd024, which Bramble's class table didn't know, so those accounts sat at addresses the scan never derived.

  • Class table (account-families.ts): adds XVERSE_ARGENT_CLASS_HASH as an Argent entry: signer-owner-guardian-option constructor, argent-signer-array authorization, deployment + implementation.
  • Scan (onboarding-ops.ts): one extra preview per index, on the wallet's own ladder only. It is filtered out of the Ready (argentx-bip44) ladder scan, where Xverse never deploys. Cost: one derivation and one status read per index.
  • Pre-switch Xverse accounts (official Argent 0.4.0 class) were already scanned on this ladder. Unchanged.

Verification

  • Class: starknet_getClass on Mainnet (mainnet.nodes.starknet.org/rpc/v0_10) returns a Cairo 1 class with Argent's ABI (get_owner, get_owner_type, get_guardian, get_version, __validate_deploy__) and constructor(owner: Signer, guardian: Option<Signer>).
  • Source: xverse-core develop, starknet/constants.ts (argentXContractClassHashV0_4_0) and starknet/utils.ts (path, grindKey, calldata, salt, deployer 0).
  • Tests:
    • account-candidates-xverse.test.ts rebuilds the address exactly as xverse-core does (starknet.js CallData.compile with CairoCustomEnum/CairoOption) for three keys and requires Bramble's candidate to match.
    • recovery-discovery-xverse.test.ts checks the Xverse class is previewed once per index on the own ladder only, and that a deployed one is listed as a restorable Argent candidate on starknet-bip44.
    • The existing ladder test is updated for the extra own-ladder shape.
  • Mutation checks (each fails the new tests): dropping the scan shape (4 fail), dropping the Ready-ladder exclusion (2 fail), one wrong class-hash digit (4 fail), wrong constructor shape (3 fail).
  • bun run check passes. bun run check:coverage passes (functions 95.54%, lines 96.12%). E2E not run (the machine was loaded by other jobs).
  • Merges cleanly with recovery + ledger: list Braavos accounts like Ready's, and find them in first-run Ledger setup (#718) #733 (git merge-tree).

Not in this PR (decision for owner)

Copy for owner review

  • Picker row title for these accounts: "Account N · Argent 0.4.0 (Xverse)" (from the class label). They are listed in the Argent / Ready group.

Files on the key-derivation / discovery path

  • packages/foundation/wallet-model/src/accounts/account-families.ts
  • apps/extension/src/background/onboarding/onboarding-ops.ts

🤖 Generated with Claude Code

Xverse derives Starknet keys on this wallet's own ladder
(m/44'/9004'/{i}'/0/0, grindKey) and deploys with salt = public key and
the Argent 0.4.0 constructor, but since 2025-06-30 at its own Argent
build 0x663fc01a…bd024, which the class table did not know. Recent
Xverse accounts therefore landed at addresses the scan never derived.

Add the class to ACCOUNT_CLASSES (argent, signer-owner-guardian-option,
argent-signer-array) and scan it once per index on the own ladder. It is
kept off Ready's argentx ladder, where Xverse never deploys.

Refs #734
Refs #727

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes seed-import derivation and class recognition for a third-party Argent build; wrong ladder or hash would miss or mis-label accounts, but scope is recovery scan plus catalog entries with strong regression tests.

Overview
Seed recovery can now find Xverse Starknet accounts that use Xverse’s distinct Argent 0.4.0 contract class (XVERSE_ARGENT_CLASS_HASH), which was missing from the class catalog and never derived during scan.

The wallet model registers that class like other Argent deployments (0.4.0 constructor + signer-array auth) and clarifies that deployment in the table means “may exist on chain,” not “Bramble deploys this.” Recovery scanning adds one preview per index on Bramble’s own BIP-44 ladder for the Xverse class and drops it from the Ready (argentx-bip44) ladder, matching how Xverse derives keys. Deploy behavior for Xverse-funded counterfactuals is unchanged: the picker labels them “Argent 0.4.0 (Xverse)”, says Bramble cannot deploy that release, and still blocks unused Xverse-shaped rows with no activity.

Tests cover xverse-core-compatible address derivation, background discovery (ladder choice, deployed/funded vs empty), and the sidepanel recovery gate copy/selection rules; the general Argent ladder test expects one fewer Ready scan shape and one more own-ladder shape.

Reviewed by Cursor Bugbot for commit 5821796. Bugbot is set up for automated code reviews on this repo. Configure here.

@derek-flossman

Copy link
Copy Markdown
Collaborator Author

AI-assisted review (Claude, with an independent Codex gpt-6-astra pass), posted from @derek-flossman's account.

Medium — signing compatibility only checked at ABI level. The class is classified argent-signer-array, but tests verify addresses and discovery only, and the discovery test mocks getArgentSigningRestriction() to null. Before release: QA should make one real Mainnet transaction from an Xverse-created account, and ideally add a fixture-backed owner/guardian decoding test for this class.

Follow-up held until #733 merges: deploying funded but undeployed Xverse accounts (patch drafted; needs a live deploy + transfer test).

Assert per index that Xverse's Argent build is previewed exactly once on
the wallet's own ladder and never on Ready's argentx ladder. Cover the
common real case: a funded, undeployed Xverse account is found and the
picker says Bramble cannot deploy that release, while an unused one is
never kept or selectable. Note on AccountClassRole that "deployment"
means an account may have been deployed with the class, not that this
wallet deploys it.

Refs #734
Refs #727

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@adrienlacombe adrienlacombe left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice, well-sourced change. I checked the key facts independently:

  • Class hash: xverse-core develop starknet/constants.ts has argentXContractClassHashV0_4_0 = 0x663fc01a…bd024, and starknet_getClass on mainnet.nodes.starknet.org/rpc/v0_10 returns a Cairo 1 class whose ABI includes argent::account::interface::IAccount. It matches XVERSE_ARGENT_CLASS_HASH.
  • Derivation and address: xverse-core's getAccountDerivationPath is m/44'/9004'/{i}'/0/0 with grindKey. createAX040W0GContractDescription uses owner = Signer::Starknet(pubkey) and guardian = None, and getExpectedAccountContractAddress uses salt = pubkey and deployer 0. That matches the new test and the own-ladder-only scan shape.
  • No mis-attribution or secret risk. Each candidate address comes from the user's own derived key, so a hit can't belong to someone else. Unused Xverse addresses are never listed (not "creatable"). The PR adds no key storage or logging.
  • Scope of the class-table change: Ledger derivation picks one class per family via ledgerDeployClassHash (the pinned Argent class), so the new entry doesn't add probes to Ledger scans. Deploying still only accepts the pinned 0.4.0 class.
  • RPC cost: one more preview per index on the own ladder only. Over a full 40-index search that's about 40 more candidates, each with its own deployment and balance reads. That's acceptable for what it finds.
  • CI on 5821796: fast-checks, test-and-publish, pr-guards and Bugbot all pass. The branch is 3 docs-only commits behind the base.

Things to keep in mind before shipping:

  1. Funded-but-undeployed Xverse accounts can be imported, but Bramble can't deploy them yet. The row says so, which is honest. But a user who imports one sees funds they can't move from Bramble until the deploy follow-up lands. Worth calling out in the v0.10.8 notes, or holding that row view-only until deploy is supported.
  2. Overlap with #733: both edit onboarding-ops.ts. Your recoveryScanShapes hunk ends a few lines above #733's isCreatableCandidate hunk. Both also add tests to sidepanel-recovery-scan-gate.test.ts and recovery-discovery.test.ts at different spots. They don't overlap, and I agree with your merge-tree result. Whichever merges second should still re-run fast-checks, since both change the expected scan shapes. Your deployableHere follow-up after #733 is the right order.
  3. Still to check live (from your list): a real activated Xverse account, get_version(), and one Mainnet transfer to confirm argent-signer-array signing on this build.

Copy note for the owner: rows will read "Account N · Argent 0.4.0 (Xverse)" inside the Argent/Ready group.

@derek-flossman

Copy link
Copy Markdown
Collaborator Author

Review follow-up (AI-assisted, by Claude), posted from @derek-flossman's account.

Thanks @adrienlacombe. Follow-up on your "still to check live" point, and the owner decision.

Xverse class vs the pinned Argent 0.4.0 class. I fetched both with starknet_getClass on public Mainnet RPC:

  • ABI identical; entry_points_by_type identical; get_version and get_owner_type present.
  • The Sierra programs are the same length (30,239 words) and differ in one word, index 871: 0x417267656e744163636f756e74 ("ArgentAccount") vs 0x…587665727365 ("ArgentAccountXverse"), the contract's name constant.
  • Nothing in Bramble reads that name.

So __validate__/__execute__, is_valid_signature, outside execution and the constructor are the same code as the class we already sign for, and argent-signer-array signing applies unchanged. One live Mainnet transfer before release stays as a final confirmation, not an open question.

Owner decision (#1 in your review): keep funded but undeployed Xverse rows importable with the "can't deploy" copy, and follow up in v0.10.8 with the deploy patch after #733 merges. It's small given the identical constructor. If that slips, the release notes will call it out.

Run on this PR merged onto current release/v0.10.8 (which now includes #741 and #762):

  • types, lint, files, imports, cycles and dead code pass;
  • bun run test: 3042 pass, 0 fail;
  • wallet-ui: 2107 pass, 0 fail; wallet-model: 64 pass, 0 fail.

Merge-tree: no conflicts with #731, #733, #766 or #768. #755's conflicts come from #741/#762, which are already on the base, not from this PR.

@derek-flossman
derek-flossman merged commit 3a13a2d into release/v0.10.8 Oct 26, 2026
5 checks passed
@derek-flossman
derek-flossman deleted the fix/734-xverse-class-hash branch October 26, 2026 18:16
@derek-flossman

Copy link
Copy Markdown
Collaborator Author

Merged by the repo owner via the release-review bypass; no second review. Head 94ade16 was up to date with release/v0.10.8, with fast-checks and pr-guards green.

derek-flossman added a commit that referenced this pull request Oct 26, 2026
Merged with today's release/v0.10.8 (#763 added Xverse tests to the
same files), recovery-discovery.test.ts reached 502 lines and
sidepanel-recovery-scan-gate.test.ts 510, which check:files refuses.
No test changes:
- The index-zero listing test moves to recovery-discovery-listing.test.ts.
- The picker fixtures move to tests/support/recovery-picker-harness.ts,
  the same file name and export style #755 uses for them.

Refs #718
Refs #727

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
derek-flossman added a commit that referenced this pull request Oct 26, 2026
Resolves the conflict with #763 (Xverse) in recoveryScanShapes. Bramble's
own ladder scans every Argent deployment release, Xverse's build included.
Ready's argentx ladder scans all but Xverse's build. The discovery test
asserts both counts.

Refs #776
Refs #727

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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