mirror of
https://github.com/luxwallet/create.git
synced 2026-10-30 19:49:39 +00:00
Generator that scaffolds a ready-to-run branded Lux Wallet web app for a new
chain/org from a single BrandConfig. One command per new chain.
- CLI `create-lux-wallet <brand-ref> [outDir] [--force]` + programmatic
generate(brand, outDir): validates the brand via @luxwallet/brand's
defineBrand, then stamps apps/web/ (Vite + React) that mounts @luxwallet/ui
via WalletUIProvider, authenticates with @hanzo/iam (HIP-0111), reaches
chains through @luxwallet/sdk, and ships the brand's /brand.json.
- DRY runtime-brand.json strategy: ONE brand-neutral app shell, byte-identical
across brands (enforced by test). Only public/brand.json + public/logo.svg
differ. No per-brand forks. *.tmpl files get {{brand.*}} interpolation.
- Example brands lux/hanzo/zoo/pars with canonical @luxwallet/chains ids
(lux-c 96369, zoo 200200, hanzo 36963, pars 494949) + _template.json.
- New chains: add to @luxwallet/chains registry, reference id in brand.chains[].
- MIT, zero GPL — never imports @luxfi/wallet. @luxwallet/* + @hanzo/* are
workspace deps with a documented switch to npm versions once published.
Verified headlessly: CLI tsc --noEmit clean; 7/7 node:test pass (tree,
brand.json validity via defineBrand, no token leak, DRY shell identity, force,
resolution); sample generation of all four brands validates.
87 lines
3.6 KiB
Cheetah
87 lines
3.6 KiB
Cheetah
# {{brand.name}}
|
|
|
|
A branded [Lux Wallet](https://github.com/luxwallet) web app for **{{brand.name}}**
|
|
(`{{brand.id}}`), generated by [`@luxwallet/create`](https://github.com/luxwallet/create).
|
|
|
|
This is a thin Vite + React shell that mounts `@luxwallet/ui` screens, authenticates
|
|
with Hanzo IAM via `@hanzo/iam` (HIP-0111), and reaches chains through `@luxwallet/sdk`.
|
|
**The shell is brand-neutral** — everything brand-specific lives in
|
|
[`public/brand.json`](./public/brand.json), loaded at runtime by
|
|
`@luxwallet/brand`'s `loadBrandConfig()`. To re-brand, edit that one file (and
|
|
`public/logo.svg`); never fork the app.
|
|
|
|
## Prerequisites
|
|
|
|
> The `@luxwallet/*` and `@hanzo/*` packages are **not yet published to npm**.
|
|
> Until they are, install them as workspace/path deps:
|
|
>
|
|
> - In a pnpm monorepo: set each to `"workspace:*"` in `package.json`.
|
|
> - Standalone: use `"file:../path/to/sdk/packages/<pkg>"` etc.
|
|
>
|
|
> The versions pinned in `package.json` are the (future) npm versions to switch
|
|
> to once published. See the `//deps` note in `package.json`.
|
|
|
|
## Run
|
|
|
|
```bash
|
|
pnpm install # or npm install
|
|
pnpm dev # Vite dev server on http://localhost:5174
|
|
```
|
|
|
|
## Build (static export)
|
|
|
|
```bash
|
|
pnpm build # → dist/
|
|
pnpm preview # serve the production build locally
|
|
```
|
|
|
|
`dist/` is a static SPA. Deploy it to any static host (GitHub Pages, S3 +
|
|
`hanzoai/static`, etc.). The host must serve `index.html` for unknown routes so
|
|
the IAM callback path (`/auth/callback`) and client-side routing work.
|
|
|
|
## IAM registration (one-time, per brand)
|
|
|
|
Register an IAM application (HIP-0111) with:
|
|
|
|
- **client_id**: `{{brand.iam.clientId}}` (`<org>-<app>`)
|
|
- **redirect URI**: `https://<your-deploy-host>/auth/callback` (exact match)
|
|
- **scopes**: `openid profile email`
|
|
|
|
The superuser convention is `z@{{brand.domain}}` / `Ilove<App>2026!!`.
|
|
Secrets live in KMS — never in this repo.
|
|
|
|
## Brand config
|
|
|
|
[`public/brand.json`](./public/brand.json) is the validated brand. Its shape is
|
|
the `BrandConfig` from `@luxwallet/brand`:
|
|
|
|
| field | meaning |
|
|
|------------------|-------------------------------------------------------------|
|
|
| `id` | stable brand id (`{{brand.id}}`) |
|
|
| `name` | display name (`{{brand.name}}`) |
|
|
| `shortName` | compact label, e.g. "Continue with `{{brand.shortName}}`" |
|
|
| `domain` | primary domain (`{{brand.domain}}`) |
|
|
| `iam` | OIDC `serverUrl` + `clientId` + `scopes` |
|
|
| `gateway` | `rpcBaseUrl`; chains reached at `<rpcBaseUrl>/v1/rpc/<id>` |
|
|
| `theme` | token → color, applied as `--lw-<token>` CSS vars |
|
|
| `chains` | chain ids from `@luxwallet/chains` to enable |
|
|
| `logo` | optional logo URL (defaults to `/logo.svg`) |
|
|
|
|
## Adding a chain
|
|
|
|
Chains are defined ONCE in `@luxwallet/chains` (the registry), not here. To add a
|
|
new sovereign-L1 chain to this wallet:
|
|
|
|
1. Add the chain's entry to the `@luxwallet/chains` registry (id, evmChainId,
|
|
gateway `rpcRoute`, BIP-44, native asset).
|
|
2. Reference its **id** in `public/brand.json`'s `chains[]`.
|
|
|
|
Then `@luxwallet/sdk` resolves its RPC via the brand gateway automatically.
|
|
|
|
## Web3 wallet (SIWx) login — optional
|
|
|
|
The chain picker in `src/Login.tsx` drives the multi-chain SIWx flow handled by
|
|
`@luxwallet/connect` (EVM / Solana / Bitcoin / TON / XRP). That package is an
|
|
optional peer dep and is **not installed by default**. To enable it, add
|
|
`@luxwallet/connect` and follow the TODO in `src/Login.tsx`.
|