87 Commits
Author SHA1 Message Date
zeekayandHanzo Dev a8957c09db Typecheck on the native compiler, keep 6 for the tools
typescript 7.0.2 is the native compiler and exports no JavaScript API, so
next 15.5 cannot read it — it dies in writeConfigurationDefaults. It comes in
aliased as tsgo and the typecheck script calls it; typescript stays on the 6
line for next. 0 diagnostics after, identical under both compilers; the one
baseline diagnostic was an unresolved @hanzo/event/react that the install fixed.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 23:35:57 -07:00
zeekayandHanzo Dev 709b93aadf Workflows ask for the runner label that exists
One label per runner, spelled <os>-<arch>. The aliases these jobs named
were removed, and a job naming a label no runner carries waits instead of
failing.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 11:25:55 -07:00
zeekayandHanzo Dev c7345be47b Workflows ask for the runner label that exists
One label per runner, spelled <os>-<arch>. The aliases these jobs named
were removed, and a job naming a label no runner carries waits instead of
failing.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 10:24:25 -07:00
zeekayandHanzo Dev 8580dd13c6 Workflows ask for the runner label that exists
One label per runner, spelled <os>-<arch>. The aliases these jobs named
were removed, and a job naming a label no runner carries waits instead of
failing.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 01:54:58 -07:00
zeekay 4fb2f925c0 every Hanzo dependency is the version npm serves
Ranges drift once nothing moves them: a caret that has not been rewritten
since it was written pins whatever was current that day, and an exact pin
cannot even take a patch. Both are updated here.

One line per package, so a surface reads the same components, the same
tokens and the same face as every other one.
2026-09-01 16:04:45 -07:00
zeekay 476b1a6f7a reach chains at /v1/chain; the node deleted /v1/bc 2026-08-30 20:43:08 -07:00
zeekayandHanzo Dev bbc036c19d refactor(market): name the "needs a chain read" predicate once
The hook decided whether to make a request and the read decided which rows to
ask about, and both spelled the same question out for themselves. `unnamed`
answers it in one place, so the two cannot drift apart.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-29 18:19:04 -07:00
zeekayandHanzo Dev 486cae88c3 feat(market): read the item id from the indexer, and fall back to the chain
The id was recovered only from the chain's own Transfer logs, so the field the
indexer is about to start writing would have landed unused and every screen
would have kept paying for eth_getLogs to learn what it was already being told.

The indexer declares the id in two places on a transfer — token_id on the row
and token_id inside total — and neither is populated yet. Both are read, in
that order, the way the indexer itself falls through column spellings. idFor
asks the row before the log join, so one function answers "which item moved"
for every screen and nothing above it knows which source replied. The log read
is asked only about rows that arrive unnamed and does not run when there are
none, so it retires itself rather than being switched off.

/tokens/{addr}/instances is read for the same reason. It answers 200 and empty
for every collection today, so the collection page still recovers ids from one
page of transfers and says so — "50 of 149 items", not a slice presented as a
collection. When the resource fills, that list is preferred, whole, and carries
each item's own name and image; the item page takes its metadata from the same
record instead of fetching a gateway URI.

Verified against a mocked indexer carrying token_id: the ids render with the
chain RPC blocked entirely.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-29 18:19:03 -07:00
zeekayandHanzo Dev 4d8f97f19f docs(market): the Ethereum and BSC collections, measured
The import had no collection behind it. There are two, both live: Lux Genesis
(LUXNFT, 50 tokens, 28 holders) on Ethereum mainnet, and CryptoZoo (ANML, 5840
tokens, 2676 holders) on BSC. Every figure enumerated over eth_call today, with
the command beside it.

Records what an import must carry that a snapshot alone does not: lux.town has
lost its delegation, so all 100 Ethereum URIs are dead; the video is recovered
on cdn.lux.network but the metadata was a dynamic route and needs a renderer,
not a rehost. The Media contract cannot be repaired on Ethereum — only the 28
holders can rewrite their own tokens.

Weighs the three routes. The bridge corridor's contract half exists and its Go
half does not; the snapshot-and-mint is already planned and verified but leaves
the Ethereum originals alive, which the record states rather than hides.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-29 18:19:02 -07:00
zeekayandHanzo Dev c53de77512 fix(market): a trailing slash is not a different page
`trailingSlash` made the router report `/support/` for a link written
`/support`, so comparing the two raw strings matched nothing and every item in
the support nav read inactive on its own page.

One function normalises both sides, and it matches exactly rather than by
prefix. Every link in both navs is a leaf, and a prefix match lights the wrong
ones — `/support` under `/support/projects`, and `/launch` under `/launches`.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-29 18:19:01 -07:00
zeekayandHanzo Dev cb6db81c52 fix(market): the holders figure counted holdings, and nothing may rank
The indexer's holders resource serves one row per HOLDING. On an ERC-20 that
is one row per holder; on a collection it is one row per held item, so Lux
Genesis came back as three rows for two addresses and the Uniswap position
manager as fifty rows that are all the same address. The site printed "3
holders" and "73 holders" and drew one address fifty times.

explorer.holders() folds the rows by address, which is what makes the answer
countable. The collection page counts the folded list and reads 2 for Genesis,
which agrees with ownerOf. The resource pages at 50 and reports no next page on
the page that fills, so a full page says "at least" rather than a flat count.
holders_count arrives as Token.holdings, named for what it counts, and only a
screen that knows the standard prints it.

Nothing is ranked any more. Collection cards carried a position, 1 through 10,
over the order the indexer happens to answer in — which is by holder count — on
a site whose own launches page says a default that puts one project on top is a
recommendation it is not entitled to make. Collections arrive by name.

Also read against the chain and corrected: /launches said the indexer reports
decimals as 0 for Zoo tokens that carry 18. Those contracts return 0 from
decimals() themselves, so the claim was false and the reason for omitting
supply is the real one. /support/projects claimed collection-level data was
complete, including holder count and full transfer history; it is a page of
transfers and a holdings count, and now says so.

An application no longer requires a session to compose. A filled-in form
produced nothing at all without Hanzo IAM, directly under a paragraph saying
signing in was not a condition of applying. Signed in it names the applicant;
signed out the record says the reply goes to the address it arrives from.

/item threw during render on ?id=abc and took the page to a blank screen.
Holdings drew a chain whose read had FAILED as no holdings at all. usd()
rounded a pool holding forty cents to $0, the same thing an empty pool prints.
The header lit both Launches and Apply on /launches, on a shared prefix.

The launches table read the indexer itself, with its own token type and its own
fetch; it uses lib/explorer like every other screen.

trailingSlash, because the export wrote support.html beside a support/
directory and a host that prefers the directory served a listing where the page
belongs. Every route is now its own index.html and needs no rewrite rules.

Removed from public/: reservoir's logos, 80 chain icons for chains Lux does not
run, ten foreign chain logos, and og-image.png — a Reservoir Explorer marketing
card advertising Bored Ape floor prices, sitting in the social-preview slot of a
site whose whole point is that it quotes no prices. The two radix packages whose
only consumers were the deleted listing dialogs go with them.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-29 18:19:00 -07:00
zeekayandHanzo Dev 0a4ca354cd chore(market): utils keeps the two functions the app calls
formatDate, formatNumber, formatCurrency, formatPercent, isAddress,
debounce and absoluteUrl had no callers left after the rebuild. cn and
shortenAddress do.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-29 18:19:00 -07:00
zeekayandHanzo Dev 87a4f1dff8 fix(market): quote the royalty from basis points, not a float
ERC-2981 quotes an amount against a sale price rather than publishing a
rate, so the rate is read by asking for one whole token and dividing.
Doing that in floating point printed 250 basis points as
2.4999999999999996%. rateLabel scales by 10,000 in bigint first, so the
integer the contract stores comes back out intact.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-29 18:18:59 -07:00
zeekayandHanzo Dev f216bef77b feat(market): rebuild the surface on the reads that answer
The market advertised a marketplace it does not have and could not open
a single collection. Every card linked to /collection/{chainId}/{address}
through a field the indexer does not send, into a route that did not
exist; the homepage printed four Genesis tiers nothing had read and named
Seaport and LSSVM as its protocols, neither of which is deployed on any
Lux chain; the activity feed rendered forty-five identical rows of
"NFT #?".

WHICH CHAINS EXIST IS NOW READ, NOT DECLARED. lib/chains.ts held a list
that had drifted twice — it missed Osage and it offered SPC, whose RPC
404s and which the indexer's registry has never served, and it pointed
Pars at an /ext/ path that 404s. All of it is gone. readChains() reads
/v1/explorer/admin/chains and every screen carries a whole chain record:
slug for the indexer, id for a contract, coin for a label, explorer for a
link out. Two things the registry does not hand over cleanly are handled
once, in one place: its `rpc` is the indexer's own in-cluster route and
the browser's arrives as `public_rpc`, and its order is a Go map's, so
the switcher sorts rather than reshuffling on every load.

THE ITEM ID IS RECOVERED FROM THE CHAIN. The indexer writes the ERC-20
shape into every ERC-721 transfer and discards topics[3], which is why
the feed had nothing to distinguish one row from the next. Its log_index
is the EVM log index, so (block, logIndex) joins a row to its log
exactly; lib/logs.ts does that join in bounded windows and rows outside
the budget say the id was not read. Forty-five anonymous rows are now
forty-five named items.

/genesis WAS PROBING A CONTRACT WITH NO CODE. The collection is alive at
0x9e04fc57.. and answers everything: three minted, three billion LUX
bonded, a 2.5% royalty declared through ERC-2981, and a `market` address
of zero, which is the collection saying nothing is wired to sell it. It
also keeps a record per token, the only per-item metadata on any Lux
chain, so each token shows its real name, tier and bonded amount.

NEW: /collection and /item, the two routes a marketplace cannot be
without. They take the chain and address in the query because a static
export cannot render a path segment for a contract deployed after the
build. /pools reports the AMM — 32 pools on Lux, 20 on Zoo — with totals
read from the factory entity rather than summed over a partial page.
A footer reaches applying, support, terms and privacy from every page.

GONE: ListingForm, OfferForm, TraitFilter, the IMarket ABI and the LSSVM
pair ABI. Market.sol is deployed nowhere, so a listing form against it is
a button that lies. They come back when an address does.

Failed reads now throw instead of resolving to an empty page, because a
list cannot otherwise tell "there are none" from "we could not ask" — and
those mean opposite things. Every screen names the chain it read.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-29 18:18:58 -07:00
zeekayandHanzo Dev 4e02bd8b6e fix(market): the page ground came from the gui engine, not the token set
@hanzo/gui writes its own tokens at runtime — `:root.t_dark { --color: …;
--background: … }` plus `body { background: var(--background); color:
var(--color) }` inside a prefers-color-scheme block. `--background` is a
name both it and @luxfi/ui/tokens.css use, for different things, and the
injected rule is later in the cascade and more specific, so bg-background
resolved to hsla(0,0%,97%,1) on a page whose cards were #0A0A0A. Card
text measured 1.03:1 against its own card; AA wants 4.5:1.

Read the ground from `--color-bg-body` instead — the token set's own name
for the page ground, which nothing else defines and which tracks the same
rungs `--background` does, n-0 in light and n-1000 in dark. A rename at
the point of use, not a second opinion about the colour. Measured after:
body 20.12:1, card 18.97:1.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-29 18:18:57 -07:00
zeekayandHanzo Dev a89bfefcfe build(market): TypeScript 6.0.3 — Next 15 drives the JS compiler API
Next 15.5.22 reads tsconfig paths and typechecks through the TypeScript
JavaScript compiler API. TS 7's native compiler does not expose it, so
`next dev` refused to start, `next build` could not resolve the `@/*`
alias declared in tsconfig.json, and next.config.ts failed to load at all
(the comment in next.config.mjs records the third symptom).

6.0.3 is the newest release Next can drive. Dev server, build and alias
resolution all come back with it.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-29 18:18:56 -07:00
zeekay a14037b6b4 delete the sanity caller that points at nothing
It calls hanzoai/.github/.github/workflows/workflow-sanity.yml@main, and that
file does not exist — the repo holds docker-build, platform-build and promote
and nothing else. Every push has opened a run that fails before a step, and
this repo now has one pipeline address, in .hanzo/workflows/cicd.yml.
2026-08-20 19:04:03 -07:00
zeekay 9656de4c19 call the canonical pipeline
Seven lines of triggers; every knob is in hanzo.yml.
2026-08-20 19:04:02 -07:00
zeekay 2b41b5f0ee gate market on tsc, run on the native fleet
Install then tsc --noEmit, measured clean. The install matches the Dockerfile's
because the lockfile is behind package.json by one dependency.
2026-08-20 19:04:01 -07:00
zeekay 13094feabf delete the GitHub-hosted workflows
publish.yml computed and pushed a version tag on ubuntu-latest; the two
sync-*-branches jobs auto-merged dev into staging, polygon and vpn on
ubuntu-latest, a branch model that came with the fork and that this repo does
not use. The image build is untouched — docker.yml on lux-build and
release-matrix.yml on the luxfi-* pools both stay.
2026-08-20 19:02:33 -07:00
zeekay f106eed96b delete the GitHub-hosted workflows
publish.yml computed and pushed a version tag on ubuntu-latest; the two
sync-*-branches jobs auto-merged dev into staging, polygon and vpn on
ubuntu-latest, a branch model that came with the fork and that this repo does
not use. The image build is untouched — docker.yml on lux-build and
release-matrix.yml on the luxfi-* pools both stay.
2026-08-20 19:02:32 -07:00
zeekay ec2fa199bf delete the GitHub-hosted workflows
publish.yml computed and pushed a version tag on ubuntu-latest; the two
sync-*-branches jobs auto-merged dev into staging, polygon and vpn on
ubuntu-latest, a branch model that came with the fork and that this repo does
not use. The image build is untouched — docker.yml on lux-build and
release-matrix.yml on the luxfi-* pools both stay.
2026-08-20 19:02:30 -07:00
zeekayandHanzo Dev 0bcee42adf feat(market): send pageviews to Hanzo Insights
The marketplace shipped with no telemetry of any kind — no pageviews, no
sessions, no errors — so there was no way to say whether anyone uses it, or
which collection they came for. It is one of seven Lux surfaces going dark in
the same way, and all seven report through @hanzo/event, which posts to our own
door at api.hanzo.ai and to nobody else. A marketplace's traffic is not a thing
to hand to a third party, so no tag manager and no vendor script.

The provider wraps the client tree at the root, which is what makes every route
counted from one place. It sits outside the dynamically loaded wallet and
account providers on purpose: that chunk carries wagmi, IAM and the gui engine,
and a visitor whose wallet never arrives is exactly the visitor worth hearing
about. The provider counts the first load and usePageview counts every
navigation after it, so a single-page app stops looking like one visit that
never moves.

The ingest key is publishable — it attributes a write and can read nothing, so
it belongs in the bundle the way a public address does. An env override lets a
deploy swap it; the literal is what makes the site report today, since the
image is built with no arguments.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-13 11:49:15 -07:00
zeekayandHanzo Dev 338372bf11 fix(market): a public repo cannot call a private reusable workflow
Every docker.yml run in this repo has died at 0s with "workflow file issue"
and zero jobs created, through two different reusable targets
(hanzoai/.github, then luxfi/.github). The YAML was never the problem.

luxfi/market is a PUBLIC repository; luxfi/.github and hanzoai/.github are
both PRIVATE. GitHub will not resolve a private reusable workflow for a
public caller and fails the run before any job starts. Positive control:
luxfi/finance is private, and the byte-identical call starts and builds.
workflow_dispatch cannot be used to probe this — the dispatch API answers
422 "Actions has been disabled for this user" — so the tag push is the only
trigger, and the only signal, available.

So the build is inline: buildx on the luxfi ARC scale set (runs-on takes the
SET NAME as its label), GITHUB_TOKEN login to ghcr.io, one linux/amd64 image
pushed as :<tag-version> and :latest. That unblocks shipping the /genesis
live read, which has been stuck behind this since 1.0.31 on 2026-06-25.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 00:37:40 -07:00
zeekayandHanzo Dev ceb3c7990a fix(market): the /genesis fix has never shipped — repair the image build
/genesis reads totalMinted() and totalLuxLocked() live and says so when the
contract does not answer. That landed in 9b7c25f. It has never reached a
browser: a page-load trace of https://app.lux.market/genesis right now still
renders the hard-coded tier table —

  Genesis   Permanently Locked 1,000,000,000 LUX   Max Supply: 10
  Validator Permanently Locked   100,000,000 LUX   Max Supply: 100
  Mini      Permanently Locked    10,000,000 LUX   Max Supply: 1,000
  Nano      Permanently Locked     1,000,000 LUX   Max Supply: 10,000

— 40B LUX of "permanently locked" behind 0x004287c4..76c6, which has NO CODE:
eth_getCode on https://api.lux.network/v1/bc/C/rpc returns "0x" at block
1098195, positive controls WLUX 0x4888E4a2.. -> 3462 hex chars and Multicall3
0xd25F88CB.. -> 2592.

The live pods run ghcr.io/luxfi/market:1.0.31-amd64, built 2026-06-25. Tags
v1.0.32 through v1.1.4 produced no image at all: docker.yml carried a
top-level `permissions:` block alongside `secrets: inherit` on a `uses:`,
which fails the run at 0s with "workflow file issue" before any job starts —
and it targeted `["self-hosted","linux","amd64"]`, a label array that names
hanzoai-org scale sets not visible from luxfi. Both fixed by using the shape
that is actually building luxfi/finance: same-org reusable, no permissions
block, ARC scale-set name as a scalar label.

- next.config.ts -> next.config.mjs: Next 15's TS config loader calls
  ts.sys.fileExists off the app's own typescript, which TypeScript 7 does not
  export, so `next build` died before the first request. A config file that
  annotates one object literal does not need types.
- next 15.5.0 -> 15.5.22, @luxfi/ui 7.4.9 -> 7.4.10 (patch only).

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 00:26:30 -07:00
zeekayandHanzo Dev f90d003296 build: typescript ^7.0.2 (native compiler)
TypeScript 7 is the native Go compiler; the npm package is a thin shim
that resolves a platform-specific native binary.

Safe here because the build does not emit through tsc — the bundler does,
so tsc is typecheck-only and the built artifact is unaffected. Gated on a
measured comparison of both compilers against this same config: TS7
introduces no errors TS 5.9 did not already report.

typescript now ^7.0.2

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 19:10:21 -07:00
zeekayandHanzo Dev fa3eb64ce9 fix(market): a chain is a name, not a colour
CHAIN_INFO carried a `color` per chain — five hexes lifted wholesale from
GitHub's dark-syntax palette: #7ee787 (entity green), #d2a8ff (entity),
#ffa657 (variable — the literal tan the owner called out), #ff7b72 (keyword),
plus a cyan #55ccff for Lux itself. They were painted as inline
`style={{ color }}` in seven places on a surface whose every other pixel is
achromatic, and an inline hex is unreachable by white-label-by-hostname no
matter what value it holds.

Deleted rather than re-tokenised: the field existed to make five chains
distinguishable and the chain NAME already does that. The active chip in the
header was `text-black` over that hex, which stopped meeting contrast the
moment the fill stopped being a light pastel — it is the accent pair
(bg-primary/text-primary-foreground) now, which flips correctly with the mode.

@luxfi/ui 7.4.5 -> 7.4.9, which is also what un-breaks this app: two physical
copies of @tanstack/react-query left it rendering "Application error: a
client-side exception has occurred" with "No QueryClient set, use
QueryClientProvider to set one" in the console, on every route.

After: warm 0%, tinted-neutral 0.009%, mean chroma 0.448 at 1440x900 and
390x844, light and dark.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 19:02:22 -07:00
zeekayandHanzo Dev 93e36736d3 chore(market): lockfile follows @luxfi/ui 7.4.7
A package.json bump without the lock is a --frozen-lockfile CI failure.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 18:29:23 -07:00
zeekayandHanzo Dev 8ece470be7 fix(market): the /auth/callback route the market never had
The header offered "Sign in with lux.id" and the IdP sent the user back to
https://lux.market/auth/callback — a route that did not exist, so the login
could START and never FINISH. Next answered 404 and the code was dropped.

Same fix as the duplication above it: `@luxfi/ui/[email protected]` owns the flow, so
the route is `<AuthCallback/>` and providers.tsx is `<AuthProvider>` instead of
a verbatim copy of lux/mpc/dashboard's `configureIam` + `startLogin` + `logout`.
The market has nothing of its own to do with a fresh session.

`tsc --noEmit` clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 18:26:41 -07:00
zeekayandHanzo Dev 6628c48e4c fix: declare CSS side-effect imports for TypeScript 7 (TS2882)
TypeScript 7 reports TS2882 for a stylesheet side-effect import with no type
declaration; TS 5.x accepted them silently. Bundlers resolve stylesheets through
their own loaders, so the import never reaches the TypeScript module resolver —
this declares them legitimate rather than giving them a shape.

MEASURED, not assumed: this repo reports TS2882 under tsc 7 without the file and
zero with it. Repos where a framework already ships ambient CSS declarations
(Next's next-env.d.ts) were left alone — the declaration is inert there and was
not added.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 18:24:58 -07:00
zeekayandHanzo Dev 8f96fa5dca feat(market): one icon set — @luxfi/ui/icons, and lucide-react leaves package.json
Ten files imported `lucide-react` directly. The vintage happened to match what
@luxfi/ui resolves today, but a direct dependency is a second place the version
can move, and it has moved before — the surfaces ranged over 0.312, 0.474, 0.577,
1.26 and 1.27, which are different drawings under the same names. `Search` at
0.312 and `Search` at 1.27 are not the same glyph.

So the dependency goes and the import path becomes `@luxfi/ui/icons`, which is
Lucide as @hanzo/gui standardises on it. One package resolves the set, for every
Lux surface, and drift stops being expressible here.

Import-path change only — `git diff src` is ten single-line edits. `next build`
is clean, 6 routes prerendered.

Not screenshotted: this surface does not currently render past hydration. It
throws "No QueryClient set, use QueryClientProvider to set one" from wagmi, in
50f5b65 (refactor(market): one chrome — a wallet is not an account), which this
change does not touch. Same error, same 127-byte body, with these ten edits
reverted.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 15:07:58 -07:00
zeekayandHanzo Dev e5c807bddc refactor(market): one chrome — a wallet is not an account
lux.market had a header of its own: its own sticky bar, its own link styling, a
nav with no phone presentation at all, and a Connect button standing in for an
account menu the surface did not have. Two identities meet here and they are not
the same thing — the WALLET signs a listing, the ACCOUNT is who you are and
which org you act in — and only the first existed.

The chrome is now `AppNav` from @luxfi/ui: brand, org switcher, links, settings
and the user menu, identical to the MPC dashboard and the bootnode console, with
the links collapsing into the same gui Sheet the switchers use. The chain
selector and the wallet button stay, in the nav's free slot, because those are
this surface's own controls and not chrome.

Identity comes from IdentityProvider (IAM); brand, theme, issuer and IAM client
come from the Host header, so lux.market and a zoo-branded market are one image.
The gui engine's bundler wiring comes from `withLuxUi`, not a hand-rolled
transpile list.

`next build` passes: 6 static routes exported.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 15:00:04 -07:00
zeekayandHanzo Dev 9e56f246d0 fix(market): /genesis printed a tier table no contract backs — read it instead
The page rendered four hard-coded tiers claiming 10x1B + 100x100M +
1000x10M + 10000x1M LUX "permanently locked", plus per-tier "10x/5x/2x/1x
rewards". None of it came from anywhere:

- The collection 0x004287c47efc912fec391979154454a8017a76c6 has NO CODE at
  head. Measured on https://api.lux.network/v1/bc/C/rpc at block 1098191:
  eth_getCode -> "0x", totalSupply() -> "0x" (revert). Positive control
  WLUX 0x4888e4a2.. -> 3462 hex chars and a live totalSupply.
- The supplies contradicted the tokenomics reference: NFT-COLLECTION.md
  has Genesis Validator count 100 (not 10) and records that the
  Validator/Mini/Nano hierarchy is "tokenomics-designed but not issued".
- GenesisNFTs.sol has no reward-multiplier concept at all. The 10x/5x/2x/1x
  figures were invented outright.

Now the page calls totalMinted() and totalLuxLocked() — both real reads,
GenesisNFTs.sol:829 and :214 — and renders whatever chain returns. When the
call reverts, as it does today, it says supply and bonded LUX are
unavailable and names the address, rather than substituting a number.

Also drops src/lib/wagmi.ts: a second createConfig that nothing imported,
shadowing the live one in app/providers.tsx.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 14:10:00 -07:00
zeekayandHanzo Dev 6c5ece0bb3 chore(market): one icon vintage — lucide-react 1.27, the same set every Lux surface renders
lux.market drew Lucide at 0.511 while the console drew it at 1.27 and lux.vote
at 0.312. Same set, three vintages — and Lucide redrew a lot between 0.3x and
1.x, so the same named glyph came out a different shape depending on which
surface you were looking at. One vintage now, matching the console and matching
the geometry the explorer's sprite is generated from.

All eleven glyphs the marketplace uses (ArrowRight, Check, ChevronDown,
ChevronRight, ChevronUp, Circle, ExternalLink, LogOut, Search, Wallet, X) exist
under the same names in 1.27; `next build` exports all six routes clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 13:39:04 -07:00
zeekayandHanzo Dev aa14e5189d fix(market): real NFT read path — every data hook was a hard-coded empty stub
app.lux.market rendered "No NFT collections found on Lux yet" unconditionally:
src/hooks/useNFTData.ts and src/lib/explorer.ts returned {items:[]} literals, so
no request was ever made. The URLs they would have used were dead anyway.

Measured against live mainnet 96369 and fixed:

- lib/chains.ts: EXPLORER_API pointed at https://explore.lux.network/api/v2 —
  404 (that host serves the Next.js frontend, not an API). The live read API is
  the unified indexer at https://api-explore.lux.network/v1/indexer/<slug>,
  slugs from its own /v1/explorer/admin/chains. CORS is `*`.
- lib/chains.ts: all five rpcUrls 404'd (`/mainnet/ext/bc/...`). Public form is
  `/v1/bc/C/rpc`; the four reachable ones now verified via eth_chainId. SPC has
  no public RPC and is marked as such.
- lib/chains.ts: Pars was chainId 17471; it is 494949 (eth_chainId 0x78d65).
- lib/chains.ts: CHAIN_INFO gained `color`, read by three pages that had been
  typing it as a missing property.
- lib/explorer.ts: real typed fetchers, one data-access layer. The indexer
  ignores `?type=`, so the ERC-721/ERC-1155 filter is applied client-side.
- hooks/useNFTData.ts: thin react-query wrappers over those fetchers.
- app/activity: dropped its private copy of the fetch (used `tx_hash`; the API
  field is `transaction_hash`) in favour of the shared hook.
- ActivityRow: derives the explorer URL from the chain object instead of string
  surgery on the API base.
- contracts.ts: MARKET_ABI was `[]`. Filled from the real interface at
  standard/contracts/nft/Market.sol:37-48. ERC721_ABI gained the `approve` entry
  ListingForm calls.
- ListingForm/OfferForm addressed `contracts.markets`; the field is `market`.
- OfferForm sent paymentToken=address(0) plus native `value`. makeOffer is
  non-payable and reverts on address(0) (Market.sol:418) — every offer would
  have reverted. Now denominated in WLUX, verified on-chain (1730 bytes, 18dp).
- next.config.ts: ignoreBuildErrors was hiding all 40 of the above type errors.
  Turned off; `pnpm build` is green with checking on.

CONTRACTS stays empty: Market.sol is deployed on no Lux chain. The recorded
mainnet address (addresses.json markets/Markets 0xefba7dbf…) has no code — so
list/buy/offer remain unreachable by design until it is redeployed.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 12:06:20 -07:00
zeekay 076892afab chore: restore upstream attribution + NOTICE (OSS compliance) 2026-06-21 07:52:50 -07:00
zeekay a04876ddf4 ci: route to canonical native arcd labels [self-hosted, linux, <arch>]
Replaces non-canonical scale-set / org-prefixed labels with the
existing labels every arcd host registers with. Matches evo for
amd64 and spark for arm64. No new labels added.
2026-06-10 20:23:32 -07:00
zeekay 21b8e9aa5a ci: cross-platform release matrix on self-hosted runner pools 2026-06-02 11:06:02 -07:00
zeekay 10011efc4c ci: pin runner-amd64/arm64/deploy to luxfi pool labels
Was using canonical workflow defaults (hanzoai-scoped labels) which
do not dispatch for luxfi org. Switched to round-robin pool labels:
  runner-amd64: luxfi-amd64  (evo)
  runner-arm64: luxfi-arm64  (spark + dbc, round-robin)
  runner-deploy: lux-deploy-linux-amd64  (DO ARC pool)
2026-06-01 17:41:42 -07:00
zeekay d96614bdec merge: ci/canonical-docker-build 2026-06-01 16:35:25 -07:00
zeekay c31ffc213a chore: drop stale yarn.lock, declare packageManager: [email protected]
Project already had pnpm-lock.yaml; yarn.lock was stale. Pinning the
packageManager field locks the local toolchain to pnpm so commit
hooks and CI agree.
2026-05-25 23:15:16 -07:00
zeekayandGitHub 5dbdf29ca4 chore: add LICENSE (Lux Ecosystem License v1.2) + LICENSING.md pointer (#68)
* chore: add Lux Ecosystem License v1.2

* docs: add LICENSING.md pointer to canonical IP/licensing strategy
2026-05-16 10:47:04 -07:00
zeekayandGitHub 9679cc5408 ci: migrate to canonical docker-build reusable (#38)
- Add docker.yml using hanzoai/.github/.github/workflows/docker-build.yml@main
- Add workflow-sanity.yml to enforce canonical CI contract
- Remove bespoke docker build steps from existing workflows

Refs: hanzoai/.github canonical Docker CI contract.
2026-04-23 19:12:19 -07:00
zeekay 5ffacccf62 ci: migrate to canonical docker-build reusable
- Add docker.yml using hanzoai/.github/.github/workflows/docker-build.yml@main
- Add workflow-sanity.yml to enforce canonical CI contract
- Remove bespoke docker build steps from existing workflows

Refs: hanzoai/.github canonical Docker CI contract.
2026-04-23 19:10:04 -07:00
zeekay d6e57471d2 ci: cap at v1.x.x — no major bumps 2026-04-20 21:02:55 -07:00
zeekay c0783e2ac1 ci: use GITHUB_TOKEN for tag push + persist-credentials 2026-04-20 21:00:20 -07:00
zeekay b74e2b0954 ci: auto-bump semver tags on main push 2026-04-20 20:58:35 -07:00
zeekay ea77804da5 ci: amd64-only first pass (arm64 later via native runners) 2026-04-19 01:09:48 -07:00
zeekay 0224352ab0 build: delete dynamic [chainId]/[address] routes — static export can't prerender them 2026-04-19 00:54:55 -07:00
zeekay 6658f58e59 build: drop dynamicParams (incompatible with static export) 2026-04-19 00:51:21 -07:00
zeekay 8ae79dd006 build: stub dynamic route placeholders for static export 2026-04-19 00:49:24 -07:00
zeekay c12c47abc6 build: ignore TS/ESLint errors — stubs aren't strict-typed 2026-04-19 00:46:11 -07:00
zeekay 9c799469fc fix: hook stubs return paginated shape {items,next_page_params} 2026-04-19 00:45:45 -07:00
zeekay d263bb4352 fix: hook stubs accept any args 2026-04-19 00:43:30 -07:00
zeekay 295362c9e3 fix: stub @luxfi/contracts (not on npm) 2026-04-19 00:41:12 -07:00
zeekay 9e62201716 fix: inline @luxfi/chains + @luxfi/contracts stubs (not on npm) 2026-04-19 00:38:07 -07:00
zeekay eb30aa2ade fix(docker): COPY . . before install so postinstall finds source config 2026-04-19 00:34:00 -07:00
zeekay 80f927ce39 fix: inline @luxfi/hooks stubs (package not on npm) 2026-04-19 00:33:20 -07:00
zeekay c7f8039660 fix(docker): Next static export outputs to /app/out 2026-04-19 00:28:57 -07:00
zeekay 91a0ece03e ci: standardize Vite 8 + ghcr.io/hanzoai/spa 2026-04-19 00:28:25 -07:00
zeekay 132d219de9 build: static export + ghcr.io/hanzoai/spa runner 2026-04-18 23:52:23 -07:00
zeekay 75ba7137fb chore: symlink AGENTS.md and CLAUDE.md to LLM.md
Canonical project context lives in LLM.md. Symlinks ensure
agentic coding tools (agent, Cursor, etc.) find context
automatically regardless of which filename they look for.
2026-04-01 14:09:09 -07:00
zeekay a526be76e4 refactor: use @luxfi/chains, @luxfi/contracts, @luxfi/hooks shared packages
- Replace inline chain/contract/hook implementations with @luxfi/* imports
- All 6 lib/hook files now thin re-exports from shared packages
- Standalone market at github.com/luxfi/market (removed from exchange monorepo)
2026-03-24 18:06:03 -07:00
zeekay 57b2a13d3d chore: untrack CLAUDE.md, keep as local symlink to LLM.md 2026-03-11 11:08:27 -07:00
zeekay 3061988942 docs: add LLM.md project guide 2026-03-11 10:35:37 -07:00
zeekay 182703ab14 chore: add CLAUDE.md 2026-03-09 23:28:04 -07:00
zeekay ac3daa0251 Rebuild market with Tailwind + shadcn/ui design system
Complete UI overhaul to match lux.exchange look and feel:

- Replace all inline styles with Tailwind CSS utility classes
- Add shadcn/ui components: Button, Card, Dialog, DropdownMenu, Input
- Replace RainbowKit with plain Wagmi (useAccount/useConnect/useDisconnect)
- Dark theme with HSL CSS variables matching exchange
- Inter + JetBrains Mono fonts via next/font/google
- Migrate to Tailwind v4 (@import "tailwindcss" + @theme inline)
- Rebuild all 8 components and 7 pages
- Add shared utils (cn, shortenAddress, formatNumber, formatCurrency)
2026-03-05 08:50:47 -08:00
zeekay f37135d835 fix: remove old Reservoir marketplace code, keep only new NFT marketplace in src/ 2026-03-04 18:09:12 -08:00
zeekay 0b67e0805c fix: remove stale next.config.mjs from upstream merge 2026-03-04 18:08:03 -08:00
zeekay 1ea0b3b746 feat: replace old docs marketplace with full NFT marketplace
- Explorer API client for on-chain NFT data across all 5 Lux chains
- Seaport (Market.sol) P2P trading: list, buy, make/cancel offers
- LSSVM AMM liquidity pools for NFT trading curves
- Collection browsing, search, activity feed, portfolio
- Genesis NFT featured section
- Multi-chain support: Lux, Zoo, Hanzo, SPC, Pars
- RainbowKit wallet connection with wagmi/viem
- Docker standalone build for K8s deployment
2026-03-04 17:50:19 -08:00
zeekay c004f2c37f Restore Lux branding after upstream merge 2026-02-22 01:17:25 -08:00
zeekay 2d72eb2fc4 Merge upstream reservoirprotocol/marketplace-v2 (2106 commits) 2026-02-22 01:16:23 -08:00
zeekay c1a2571cb6 chore: add LICENSE 2025-12-31 22:21:37 -08:00
zeekay d74139476c Minor fixes 2025-12-24 14:22:44 -08:00
zeekay 5e7a1109ba fix: repair malformed package.json 2025-12-19 08:26:10 -08:00
zeekay 74cc8d191a fix: use --no-frozen-lockfile for pnpm install 2025-12-19 08:17:05 -08:00
zeekay 1477a765c3 Add packageManager 2025-12-19 08:13:26 -08:00
zeekay 8fe455ee80 Add GitHub Pages deployment 2025-12-19 08:07:59 -08:00
zeekay ea027b5ce1 fix: remove Firebase dependencies for web3-first static export
- Remove Firebase auth components (LoginPanel, SignupPanel)
- Remove Firebase-dependent checkout pages
- Replace with web3 wallet connect placeholder
- Pure blockchain backend, no Firebase needed
2025-12-15 06:49:44 -08:00
zeekay 54058a9716 fix: remove searchParams for static export compatibility
Removed searchParams usage that forces dynamic rendering. For static
export (GitHub Pages), server-side searchParams is not available.
Client components now use useSearchParams hook where needed.
2025-12-15 06:42:08 -08:00
zeekay ffd532a888 Remove watch plugin dependency 2025-12-15 06:24:39 -08:00
zeekay 8fd2882eb9 Make static-export friendly: remove API routes, middleware, ignore build errors 2025-12-15 06:04:27 -08:00
zeekay cd3537d545 Add @luxfi/menu-icons to transpilePackages 2025-12-15 05:33:14 -08:00
zeekay f28ca4911b Use standalone tsconfig without monorepo reference 2025-12-15 05:27:36 -08:00
zeekay 274172df9d Enable GitHub Pages in workflow 2025-12-15 05:22:27 -08:00
zeekay d04f4e4afd Fix package.json versions and add pnpm-lock.yaml 2025-12-15 05:19:41 -08:00
zeekay 5c7eebd517 Initial setup: standalone app from lux/web monorepo
- Converted from pnpm workspace catalog references to fixed versions
- Added GitHub Actions workflow for GitHub Pages deployment
- Configured for static site export
2025-12-15 04:56:15 -08:00