* 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]>
@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 ∘ parseround-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 ofverifyProof, 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.