Files
zeekay fed29692ca feat(brand): @luxwallet/brand runtime white-label config; wire rpc + umbrella
Add @luxwallet/brand — the ONE source of white-label truth (MIT, zero deps,
mirrors the runtime brand.json pattern without depending on GPL
@luxfi/wallet-brand). BrandConfig type + defineBrand() validator + LUX_BRAND
/HANZO_BRAND examples + mutable brand singleton with getBrand()/loadBrandConfig()
(fetch /brand.json, merge in place, apply CSS theme tokens, fail safe) + emitted
brand.schema.json (draft-07).

rpc: add rpcConfigFromBrand(brand) so a brand's gateway.rpcBaseUrl flows into
getRpcUrl without rpc depending on @luxwallet/brand (structural shape). Default
gateway unchanged.

umbrella: re-export brand as @luxwallet/sdk/brand + 'brand' namespace.

Bump @luxwallet/{brand,rpc,sdk} to 0.1.0. Tests: brand 12, rpc 11 (+2). All 7
packages typecheck; verify-clean OK (no GPL, no @noble PQ).
2026-06-23 15:12:49 -07:00

71 lines
2.7 KiB
TypeScript

/**
* Emit brand.schema.json — the JSON Schema for a brand.json file.
*
* Deployments author brand.json by hand (or via their config pipeline). This
* schema gives editors validation/autocomplete and lets CI lint a brand.json
* before it ships. The TypeScript `BrandConfig` in src/index.ts is the source
* of truth; this schema mirrors it. Run `pnpm --filter @luxwallet/brand emit`
* after changing the type and commit the result.
*/
import { writeFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
const here = dirname(fileURLToPath(import.meta.url));
const out = join(here, "..", "brand.schema.json");
const schema = {
$schema: "http://json-schema.org/draft-07/schema#",
$id: "https://luxwallet.org/schema/brand.v1.json",
title: "BrandConfig",
description: "Runtime white-label brand config for the Lux Wallet stack.",
type: "object",
additionalProperties: false,
required: ["id", "name", "shortName", "domain", "iam", "gateway", "theme", "chains"],
properties: {
id: { type: "string", minLength: 1, description: "Stable brand id, e.g. 'lux'." },
name: { type: "string", minLength: 1, description: "Display name, e.g. 'Lux Wallet'." },
shortName: { type: "string", minLength: 1, description: "Short name, e.g. 'Lux'." },
domain: { type: "string", minLength: 1, description: "Primary domain, e.g. 'lux.network'." },
iam: {
type: "object",
additionalProperties: false,
required: ["serverUrl", "clientId", "scopes"],
properties: {
serverUrl: { type: "string", format: "uri", pattern: "^https?://" },
clientId: { type: "string", minLength: 1, description: "<org>-<app>, e.g. 'lux-wallet'." },
scopes: { type: "array", minItems: 1, items: { type: "string" } },
},
},
gateway: {
type: "object",
additionalProperties: false,
required: ["rpcBaseUrl"],
properties: {
rpcBaseUrl: {
type: "string",
format: "uri",
pattern: "^https?://",
description: "Gateway base URL; RPC = <rpcBaseUrl>/v1/rpc/<chainId>.",
},
},
},
theme: {
type: "object",
description: "Theme token name -> color. Applied as CSS vars (--lw-<token>).",
additionalProperties: { type: "string" },
},
chains: {
type: "array",
minItems: 1,
items: { type: "string" },
description: "Chain ids (from @luxwallet/chains) to enable.",
},
logo: { type: "string", description: "Optional logo URL." },
},
} as const;
writeFileSync(out, JSON.stringify(schema, null, 2) + "\n");
// eslint-disable-next-line no-console
console.log(`wrote brand JSON schema -> ${out}`);