Files
e7547de725 feat(desktop): shared NetworkSwitcher + WalletMenu — the ONE hanzo.network standard (#29)
* wip(desktop): GPU-node connect (gpu.rs/useGpuConnect/hanzo-auth) + luxwallet start + brand assets

* feat(desktop): native omnichain post-quantum Lux Wallet (node-independent)

Mirror of the live fix in hanzoai/gui pkgs/ai (@hanzo/ai) applied to this
repo's pre-convergence frontend tree. Replaces the hanzo-node-backed crypto
wallet — which couldn't create/show a wallet without a connected node — with a
self-contained stack under apps/hanzo-desktop/src/lib/lux-wallet:

- luxfi/crypto WASM (real FIPS-204 ML-DSA-65 + secp256k1 + keccak); EVM keys via
  BIP-44 keys.deriveSecp256k1 (bit-identical to ethers/MetaMask), PQ identity
  via keys.serviceIdentity. Secrets sealed in OS keychain, never plaintext.
- create / import / list / reveal / balance / send across the 11 ready EVM
  chains (@luxwallet/chains + /rpc); non-EVM X/P/Q/Z marked "coming soon".
- Sign-In-With-Wallet: /v1/iam/web3/nonce -> CAIP-122 -> EIP-191 sign ->
  /v1/iam/web3/verify (@luxwallet/connect + @luxfi/crypto).
- local-HD-PQ default; MPC / Safe selectable (coming soon).

Wiring: rewrite pages/crypto-wallet.tsx onto the store; node-independent /wallet
route + "Sign in with Wallet" on quick-connection; drop dead wallets-context.
MIT/BSD deps vendored under apps/hanzo-desktop/vendor.

NOTE: this app now renders @hanzo/ai (main.tsx), so the shipping wallet fix
lands via hanzoai/gui; this mirror keeps the repo's own tree consistent.

* feat(desktop): the ONE network/wallet standard — shared NetworkSwitcher + WalletMenu

Aligns the desktop onto the shared hanzo.network model (@hanzo/ui/network +
@hanzo/ui/wallet from @hanzo/[email protected] — same standard as the hanzo
CLI and console):

- lib/network.ts: ONE place composing the brand network list (hanzo →
  canonical mainnet/testnet/devnet/local envs; zoo/lux → brand mainnet)
  into the shared selected-network store.
- Sidebar footer mounts <NetworkSwitcher/> + <WalletMenu/> (menuSide=top);
  wallet auto-provisions the PQ HD account via the lux-wallet adapter
  (keychain-sealed secrets; backup stays on the crypto-wallet page).
- Selected network drives endpoints: lux-wallet brandRpcConfig gateway +
  rpc override, defaultChainId, and useChainBalance now follow the
  selection (switch env → every chain/cloud call repoints).
- styles.css: semantic token aliases + @source for the shared components.
- tsconfig: moduleResolution bundler (exports-aware; tsc clean).
- package.json: declare @hanzo/ai (was undeclared — npm install pruned it
  and broke main.tsx) + @hanzo/ui alias.

tsc 0 errors; vite build green; vitest 81/81.

* docs(LLM.md): the network/wallet standard — seams + gotchas

* chore(desktop): bump @hanzo/ui-shadcn 5.7.3 -> 5.7.4 (genesis-canonical chain IDs)

Picks up the corrected network set (testnet 36962, devnet 36964, local
1337 @ :9630/v1/bc/C/rpc). tsc 0; vite build green.

---------

Co-authored-by: hanzo-dev <[email protected]>
2026-07-08 09:12:15 -07:00
..

@luxwallet/connect

Multi-chain wallet connect + Sign-In-With-X for EVM, Solana, Bitcoin, TON, XRP, Polkadot.

One vocabulary, one canonical login message (CAIP-122), one verifier. MIT licensed — zero GPL. This is the clean wallet stack; the Uniswap-derived GPL bones stay quarantined in luxfi/exchange.

Why

@luxfi/wallet (Uniswap "Universe" fork) is GPL-3.0 and EVM-only. This package is a from-scratch, permissively-licensed connector that any Hanzo/Lux/Zoo/Pars surface — hanzo.id login, the browser extension, web and mobile apps — can use to authenticate a wallet on any supported chain.

Architecture

connect(chain) ─► Account ─► signLogin(challenge) ─► SignedProof ─► verifyProof()
                  (browser, per-chain connector)      (server, one pure fn)
  • caip122.ts — render/parse the canonical login message. build ∘ parse round-trips.
  • verify.ts — verifyProof(proof, expected): parse → enforce domain/nonce/time → dispatch to the per-chain crypto verifier. Pure, fails closed, never throws.
  • <chain>/ — per-chain connector (browser) + verifier (pure crypto).
  • go/walletconnect — Go port of verifyProof, imported by Hanzo IAM so the server verifies identically.

Chain support

Chain Connect lib (license) Login proof Connector Verifier
EVM viem (MIT) — EIP-6963 / window.ethereum EIP-191 personal_sign ✅ evm/connect.ts ✅ secp256k1 recover
Solana injected provider (Phantom/Solflare/Backpack) ed25519 signMessage ✅ solana/connect.ts ✅ ed25519
Bitcoin sats-connect (MIT) — Xverse/Leather/Unisat BIP-322 ✅ bitcoin/connect.ts ✅ legacy + BIP-322
TON @tonconnect/sdk (Apache-2.0) ton_proof ✅ ton/connect.ts ✅ ed25519 envelope
XRP @crossmarkio/sdk (MIT) — Crossmark signInAndWait ✅ xrp/connect.ts ✅ secp256k1 + ed25519
Polkadot window.injectedWeb3 (polkadot.js / Talisman / SubWallet) signRaw({type:'bytes'}) ✅ polkadot/connect.ts ✅ sr25519 + ed25519 + ecdsa

All connect libs are MIT/Apache/ISC — no GPL anywhere in the dependency tree. Polkadot verify uses @polkadot/util-crypto (Apache-2.0, sr25519 via @scure/sr25519 MIT) in TS, and oasisprotocol/curve25519-voi (BSD-3-Clause) in Go — deliberately NOT the LGPL-3.0 ChainSafe/go-schnorrkel. Polkadot's verifier is async (sr25519 needs cryptoWaitReady()); use verifyProofAsync for all chains or verifyPolkadot standalone. The five other chains' verify core stays @noble-pure and synchronous. GemWallet is intentionally not wired: its only client, @gemwallet/api, ships under a custom dual license requiring GemWallet's permission for public/commercial use — incompatible with the MIT/Apache/ISC-only rule. Crossmark covers both XRPL key types, so the XRP path is complete without it.

Architecture: server verify never pulls a wallet lib

The wallet libraries are optional peer dependencies. The server-side verifyProof path imports only @noble/* + bs58:

import { verifyProof } from '@luxwallet/connect/verify';     // zero wallet libs
import { buildSiwxMessage } from '@luxwallet/connect/caip122'; // zero deps

Connectors live behind separate entrypoints, so a server bundle stays clean:

import { loginWithWallet, getConnector } from '@luxwallet/connect/connectors';
import { EvmConnector } from '@luxwallet/connect/evm/connect';

Use

// Server: mint a challenge
import { newChallenge, verifyProof } from '@luxwallet/connect';
const challenge = newChallenge({ domain: 'hanzo.id', uri: 'https://hanzo.id/login' });
// → store challenge.nonce, send challenge to the client

// Server: verify what comes back
const res = verifyProof(proof, { domain: 'hanzo.id', nonce: challenge.nonce });
if (res.ok) { /* res.address is authenticated on res.chain */ }
// Client (browser): connect a wallet and sign the challenge in one call.
import { loginWithWallet } from '@luxwallet/connect/connectors';

const { account, proof } = await loginWithWallet({ chain: 'evm', challenge });
// → POST `proof` to the server, which calls verifyProof(proof, { domain, nonce }).

// Or drive a connector directly:
import { getConnector } from '@luxwallet/connect/connectors';
const c = getConnector('solana');
const acct = await c.connect();             // provider.connect()
const p = await c.signLogin(acct, challenge); // ed25519 signMessage → SignedProof

Develop

pnpm install
pnpm test        # vitest — crypto verifiers run against generated keypairs
pnpm typecheck
pnpm build

License

MIT © Lux Industries Inc.