@meddleware/token-deployer-ui 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +8 -5
  2. package/package.json +19 -8
  3. package/src/App.vue +1 -1
  4. package/src/component-styles.css +39 -57
  5. package/src/components/GithubPush.vue +2 -2
  6. package/src/components/IconPicker.vue +44 -75
  7. package/src/components/LicensePicker.vue +2 -2
  8. package/src/components/ResultPanel.vue +2 -2
  9. package/src/components/ReviewPanel.vue +11 -3
  10. package/src/components/TokenDeployerView.vue +52 -48
  11. package/src/components/WalletBar.vue +12 -1
  12. package/src/components/WalrusBlobBrowser.vue +4 -4
  13. package/src/composables/useWalrusRelay.ts +1 -2
  14. package/src/config.ts +19 -17
  15. package/src/lib/buildPublishTx.ts +0 -10
  16. package/src/lib/deploy.ts +9 -3
  17. package/src/lib/deployExecutor.ts +18 -45
  18. package/src/lib/template.ts +3 -0
  19. package/src/lib/walrus-constants.ts +2 -2
  20. package/src/main.ts +4 -6
  21. package/src/styles.css +22 -0
  22. package/.claude/move-language-reference/SKILL.md +0 -445
  23. package/.claude/skills/move-language-reference/SKILL.md +0 -445
  24. package/.claude/skills/sui-move-bootcamp/SKILL.md +0 -128
  25. package/.claude/sui-move-bootcamp/SKILL.md +0 -128
  26. package/.editorconfig +0 -8
  27. package/.env.example +0 -72
  28. package/.gitattributes +0 -1
  29. package/.github/workflows/docker-publish.yml +0 -348
  30. package/.github/workflows/e2e-realchain.yml +0 -64
  31. package/.github/workflows/node-ci.yml +0 -43
  32. package/.github/workflows/npm-publish.yml +0 -83
  33. package/.htmlvalidate.mjs +0 -30
  34. package/.oxfmtrc.json +0 -5
  35. package/.oxlintrc.json +0 -10
  36. package/.vscode/extensions.json +0 -9
  37. package/AGENTS.md +0 -39
  38. package/CLAUDE.md +0 -166
  39. package/Dockerfile +0 -96
  40. package/eslint.config.ts +0 -63
  41. package/index.html +0 -22
  42. package/playwright.config.ts +0 -30
  43. package/postcss.config.js +0 -8
  44. package/public/CNAME +0 -1
  45. package/public/_headers +0 -12
  46. package/public/_redirects +0 -1
  47. package/public/favicon.ico +0 -0
  48. package/public/favicon.svg +0 -5
  49. package/public/og-image.png +0 -0
  50. package/public/robots.txt +0 -3
  51. package/public/sitemap.xml +0 -8
  52. package/scripts/e2e-browser.mjs +0 -15
  53. package/scripts/e2e-deploy.mjs +0 -227
  54. package/scripts/e2e-localnet.mjs +0 -67
  55. package/scripts/e2e-walrus-browser.mjs +0 -112
  56. package/scripts/gen-og-image.mjs +0 -31
  57. package/scripts/publish-localnet.mjs +0 -56
  58. package/scripts/regen-template.sh +0 -45
  59. package/scripts/sync-template-src.sh +0 -36
  60. package/scripts/verify-bytecode.mjs +0 -49
  61. package/src/__tests__/App.spec.js +0 -11
  62. package/src/composables/useAccessGate.ts +0 -127
  63. package/src/lib/accessGate.ts +0 -155
  64. package/src/lib/walrus.ts +0 -155
  65. package/stylelint.config.js +0 -33
  66. package/test-results/.last-run.json +0 -4
  67. package/tests/accessGate.test.ts +0 -113
  68. package/tests/buildPublishTx.test.ts +0 -243
  69. package/tests/deploy.test.ts +0 -149
  70. package/tests/errors.test.ts +0 -32
  71. package/tests/generatePackage.test.ts +0 -193
  72. package/tests/github.test.ts +0 -61
  73. package/tests/licenses.test.ts +0 -81
  74. package/tests/listMyTokens.test.ts +0 -30
  75. package/tests/template.test.ts +0 -93
  76. package/tests/templateArtifact.test.ts +0 -61
  77. package/tests/templateParity.test.ts +0 -55
  78. package/tests/useAccessGate.test.ts +0 -97
  79. package/tests/useWallet.test.ts +0 -74
  80. package/tests/useWalrusRelayGating.test.ts +0 -30
  81. package/tests/validation.test.ts +0 -117
  82. package/tests/walrusUpload.test.ts +0 -93
  83. package/tests/walrus_url_patch.test.ts +0 -26
  84. package/tsconfig.json +0 -19
  85. package/typedoc.json +0 -34
  86. package/vite.config.ts +0 -73
  87. package/vitest.config.ts +0 -10
package/AGENTS.md DELETED
@@ -1,39 +0,0 @@
1
- # AGENTS.md — token-deployer-ui
2
-
3
- Browser app for permissionless Sui token deployment. See [CLAUDE.md](CLAUDE.md) for full architecture and invariant documentation.
4
-
5
- ## Responsibilities
6
-
7
- - Bytecode patching of the pre-compiled Move template (`src/lib/template.ts`)
8
- - PTB construction for two-phase publish + finalize (`src/lib/buildPublishTx.ts`)
9
- - Source package generation and zip download (`src/lib/generatePackage.ts`)
10
- - Walrus icon upload via the operator relay (`@meddleware/sui-walrus`)
11
- - NFT-gate ownership check and access-proof attachment when `VITE_ACCESS_GATE_*` is configured
12
-
13
- ## Non-responsibilities
14
-
15
- - On-chain accounting or financial enforcement — the contracts handle that
16
- - Any backend process; no server dependency
17
- - Custody of keys or user funds
18
-
19
- ## Testing
20
-
21
- Three distinct categories — do not collapse:
22
-
23
- 1. **Unit tests** (`npm test`, Vitest): validation, template patching, PTB builders, generatePackage, deploy orchestration.
24
- 2. **Mocked-RPC e2e** (`npm run test:e2e`, Playwright, Chromium + Firefox): UI flow with fetch mock + mock wallet. Specs live in `integrations/token-deployer/e2e/`.
25
- 3. **Real-chain e2e** (`npm run e2e:localnet|testnet|mainnet`): publishes a real token; **never run in automatic CI**; gated by `E2E_MAINNET_CONFIRM=1` on mainnet.
26
-
27
- ## Key invariants
28
-
29
- - **Template parity:** `.mv` bytes and `files.json` must derive from the same `sui-token-template` commit. Verify with `npm run verify:template`; regenerate with `npm run regen:template && npm run sync:template`.
30
- - **Fee integrity:** treasury fee is split from gas inside the publish PTB. The vite prod build fails if `VITE_FEE_TREASURY` is unset (`assertTreasuryConfigured`).
31
- - **Injection safety:** validation in `validation.ts` + independent re-assertion in `generatePackage.ts` and `template.ts`. Never remove a downstream guard.
32
- - **No wallet-standard proxying:** Sui wallet objects must be wrapped in `markRaw()` before storing in Vue reactive state (private-field getters crash under Vue's Proxy).
33
-
34
- ## Key paths
35
-
36
- - E2e specs: `e2e/` (mocked-RPC Playwright suite; `testDir` in `playwright.config.ts`)
37
- - Move template: `@meddleware/sui-token-template` (`optionalDependencies` in `package.json`; local checkout at `../sui-token-template/` if working from the workspace)
38
- - NFT gate client: `@meddleware/nft-gate-client` (`repos/nft-gate-client/` in the workspace)
39
- - CI workflow: `.github/workflows/token-deployer-e2e.yml`
package/CLAUDE.md DELETED
@@ -1,166 +0,0 @@
1
- # CLAUDE.md — `token-deployer-ui`
2
-
3
- `@meddleware/token-deployer-ui` is a Vue 3 + Vite browser app that lets any user deploy
4
- their own Sui coin fully client-side (their wallet signs + pays gas + a trivial fee to
5
- the operator treasury) and download a matching source package. It is the browser
6
- equivalent of the `@meddleware/sui-token-template` Move package (from which it derives
7
- its pre-compiled bytecode and source templates). See the repo-root
8
- [CLAUDE.md](../../../../CLAUDE.md) for context and [README.md](README.md) for the
9
- user/operator guide.
10
-
11
- ## Dual app + library pattern
12
-
13
- This package ships as both a **standalone SPA** and an **embeddable library component**:
14
-
15
- - **Standalone SPA** (`npm run dev` / `npm run build`): `src/main.ts` mounts `App.vue`, which
16
- is a thin shell that renders `WalletBar` + `TokenDeployerView`. All deploy logic lives in
17
- `TokenDeployerView` — `App.vue` contains no state.
18
- - **Library component** (consumed by `@meddleware/dashboard`): `src/index.ts` exports
19
- `TokenDeployerView`, which is imported via the `exports["."]` entry in `package.json`. The
20
- dashboard's Vite build resolves TypeScript source directly — no separate lib build step.
21
- The dashboard supplies the wallet connection via `@meddleware/wallet-adapter`'s shared
22
- module singleton; `TokenDeployerView` reads `useWallet()` / `useNetwork()` from it and is
23
- wrapped in `WalletGuard` so it shows a connect prompt when no wallet is connected.
24
-
25
- The pattern mirrors `@meddleware/walrus-ui`, `@meddleware/seal-ui`, and
26
- `@meddleware/access-gate-ui`. See the dashboard `CLAUDE.md` for the invariant: every tool view
27
- must **not** render its own wallet bar, header, or footer when embedded.
28
-
29
- **Deploy executor note:** The wallet-adapter `Executor` only returns `{ digest }` — insufficient
30
- for the deploy flow, which requires the created objects to extract the packageId, coin type,
31
- TreasuryCap, MetadataCap and the Currency ref. `src/lib/deployExecutor.ts` uses the wallet-adapter
32
- singleton for wallet connection state, but executes through the app's own `SuiGrpcClient`
33
- (`getReadClient`) with `include: { effects, objectTypes }`, and `toSuiTxResult` (`src/lib/deploy.ts`)
34
- maps `effects.changedObjects` onto the `objectChanges` shape `extractPublishResult` reads. This is
35
- intentional — do not replace it with the wallet-adapter `buildExecutor`.
36
-
37
- **gRPC only.** Public fullnodes have deprecated JSON-RPC; every chain call (app and `scripts/`)
38
- goes through `SuiGrpcClient`, and `VITE_RPC_*` / `E2E_RPC` must be gRPC(-web) endpoints. Do not
39
- reintroduce `@mysten/sui/jsonRpc`. gRPC may render framework addresses in long form
40
- (`0x000…02::coin::…`) — match types tolerantly. E2E builds (`VITE_E2E=1`) inject a stub client via
41
- `setReadClient` because gRPC-web responses cannot be faked at the `fetch` layer.
42
-
43
- ## Architecture (the money/parity paths matter most)
44
-
45
- - **Bytecode patching** — [src/lib/template.ts](src/lib/template.ts) deserialises
46
- one pre-compiled template module ([src/move-template/](src/move-template/)),
47
- renames the module/OTW-struct identifiers in place, and overwrites five DISTINCT
48
- named constants (decimals, symbol, name, description, iconUrl), then re-serialises.
49
- Binary format v7 cannot be round-tripped by `update_identifiers`/`update_constants`
50
- ("missing field version"); `deserialize`→mutate JSON→`serialize` is the path.
51
- - **Two-phase publish** — TreasuryCap/MetadataCap are created in `init()` and sent
52
- to the sender, so they are NOT `tx.publish` results. Publish PTB
53
- ([src/lib/buildPublishTx.ts](src/lib/buildPublishTx.ts)) = publish + UpgradeCap
54
- policy + fee split from gas. A finalize PTB (only when needed —
55
- `needsFinalize`) mints supply and applies supply/metadata policies.
56
- - **Orchestration** — [src/lib/deploy.ts](src/lib/deploy.ts) sequences patch →
57
- publish → wait → (finalize) via an injectable `Executor` (so it is unit-testable;
58
- the real one is built from the wallet in
59
- [src/lib/deployExecutor.ts](src/lib/deployExecutor.ts)).
60
- - **Package generation** — [src/lib/generatePackage.ts](src/lib/generatePackage.ts)
61
- substitutes the same inputs into the canonical template text
62
- ([src/template-src/files.json](src/template-src/files.json)) and zips it.
63
-
64
- ## Invariants (do not break)
65
-
66
- 1. **Bytecode ↔ source parity.** The shipped `.mv` and `files.json` must both derive
67
- from the same `sui-token-template` commit. Enforced by
68
- [tests/templateArtifact.test.ts](tests/templateArtifact.test.ts) (defaults present
69
- in the `.mv`) and [tests/templateParity.test.ts](tests/templateParity.test.ts)
70
- (`files.json` == canonical sources). After changing the template run
71
- `npm run regen:template && npm run sync:template && npm run verify:template`.
72
- 2. **Injection safety is layered.** `validation.ts` gates the form, but
73
- `generatePackage.ts` (`assertSafeConfig`) and `template.ts` (`patchVecConstant`)
74
- re-assert `SAFE_TEXT`/`MOVE_IDENT`/length/keyword rules independently. Never
75
- remove a downstream guard on the assumption the form already checked.
76
- 3. **Fee integrity.** The fee is split from `tx.gas` to the config treasury inside
77
- the publish PTB. The vite production build fails on a zero-address treasury
78
- (`assertTreasuryConfigured` in [vite.config.ts](vite.config.ts)).
79
- 4. **No backend / no custody / no endorsement.** Keep all financial truth on-chain;
80
- the app only previews and constructs transactions. Do not add a server dependency.
81
- 5. **Lazy heavy deps.** `@mysten/walrus` and `@mysten/move-bytecode-template` (wasm)
82
- are loaded on demand (dynamic import / `?url`). Keep the shared `ICON_EPOCHS`
83
- constant in [src/lib/walrus-constants.ts](src/lib/walrus-constants.ts) so the
84
- eagerly-rendered widget doesn't pull the Walrus chunk into the main bundle.
85
-
86
- ## Walrus icons
87
-
88
- Icons are RAW blobs (not quilts) so `GET /v1/blobs/<id>` renders the exact image;
89
- an upload relay is required from browsers. `ICON_EPOCHS = 53` (Walrus's
90
- `max_epochs_ahead`; a larger single reservation aborts). Longer retention needs
91
- `extendBlobLifetime` (no keeper — operator step). Verified on testnet via
92
- `scripts/e2e-walrus-browser.mjs`.
93
-
94
- ## Walrus relay economics & deferred decisions
95
-
96
- The icon upload can charge users per upload via Walrus's **native relay tip** —
97
- no custom backend. This section records the decisions and their rationale so they
98
- survive independently of any planning doc. (Verified against walrus SDK 1.1.7 and
99
- the relay source `crates/walrus-upload-relay`.)
100
-
101
- - **Native `linear` tip is enforced on-chain — chosen for launch.** `register`
102
- bakes an auth payload `blobDigest ‖ SHA256(nonce) ‖ size` **plus** a tip transfer
103
- to the operator's address into the *same* tx the user signs. The relay verifies
104
- that on-chain tip (amount checked against the *actual received body length*, bound
105
- by nonce/size) **before** the expensive storage-node fan-out. Stripping or lowering
106
- the tip → the relay rejects the upload; no operator cost. This refutes an earlier
107
- finding that the tip "could be removed" — it is enforced now.
108
- - **The relay does no on-chain tx** (README L27) → the operator never pays gas.
109
- Storage (WAL) is paid by the **user** at registration; read/serve bandwidth is the
110
- separate public **aggregator**. The tip only needs to cover the relay's
111
- ingress + fan-out egress + RPC lookups.
112
- - **NFT / usage-ticket per-wallet gating is IMPLEMENTED (2026-08-05)** via the standalone
113
- `nft-gate` project: an `nft-gate` gateway fronts the operator relay and admits only
114
- holders of an `access_gate` NFT. The app gates the operator-relay option on ownership
115
- (`useAccessGate` → `listOwnedObjects`), offers a permissionless purchase CTA, and attaches
116
- a wallet-signed access proof (`sui:signPersonalMessage` → `uploadRelayAuthToken`) when the
117
- operator relay is used. Unset `VITE_ACCESS_GATE_*` → no gating (unchanged behaviour). The
118
- tip and the NFT are **independent levers** (tip = per-upload cost; NFT = access/abuse).
119
- - **Per-wallet rate limiting** — previously rejected at the edge (which can't resolve the
120
- wallet), it is now enforced by the `nft-gate` gateway *after* verification. Keep a per-IP
121
- edge limit as a coarse pre-auth control.
122
- - **Autonomous price-fed tip tuner DEFERRED** — the relay reads its tip only at
123
- **startup** (no hot-reload/SIGHUP), so adjusting = rewrite YAML + restart. That's a
124
- keeper with a liveness dependency. For launch use a **single static tip with a fat
125
- SUI-denominated margin**: icons are cents-scale, so a large margin costs users
126
- nothing and absorbs *both* SUI/fiat drift and storage-node retry amplification in
127
- one lever. A later tuner (read Pyth on-chain, clamp to `[min,max]`, rolling-restart)
128
- must stay under the client `max` headroom below.
129
- - **Client `WALRUS_MAX_TIP_MIST` ↔ relay-tip COUPLING** — the SDK **throws** if the
130
- relay's tip exceeds this client ceiling ([config.ts](src/config.ts) documents it).
131
- Set it with generous headroom above the relay tip; raising the relay tip past it
132
- needs a frontend redeploy.
133
- - **Client-side icon size/type limits are UX only — NOT security.** The authoritative
134
- cap is a hard request-body limit at the edge (the relay otherwise buffers up to a
135
- hardcoded 1 GiB body into RAM *before* the tip check — the one real abuse vector:
136
- ingress/RAM/RPC on rejected uploads). See the relay runbook in [README.md](README.md).
137
-
138
- ## Testing
139
-
140
- Three distinct categories — do not collapse them (repo convention):
141
-
142
- - **Pure unit (Vitest, `npm test`):** validation, licenses, github, template patch, PTB
143
- builders, generatePackage, deploy orchestration, provenance/parity.
144
- - **Mocked-RPC UI e2e (Playwright, `npm run test:e2e`):** wallet/form/publish flow against the
145
- `VITE_E2E` fetch mock + mock wallet in [src/main.ts](src/main.ts) (tree-shaken from prod). Specs
146
- live in `e2e/` (`playwright.config.ts` builds with `VITE_E2E=1` + previews). **Migrated from Cypress
147
- 2026-08-07** (Cypress dropped — it exits SIGILL in the sandbox; Playwright is the one browser-e2e
148
- tool now, shared with the real-chain harness). Run `npm run e2e:install` once, then `npm run test:e2e`.
149
- Cannot reach real confirmation, the result panel, or the source download — those need a real chain
150
- (see below). This is the automatic gate alongside `npm test`.
151
- - **Real-chain deploy e2e (Playwright, NOT in `npm test`):** `scripts/e2e-deploy.mjs` — the
152
- single network-parametrized harness (`E2E_NETWORK=localnet|testnet|mainnet`) driven by
153
- `npm run e2e:localnet|e2e:testnet|e2e:mainnet`. Injects a wallet-standard wallet backed by a
154
- node keypair, does a REAL publish, waits for real confirmation, checks the result panel,
155
- downloads the zip, and verifies coin type + fee on-chain. Two axes are distinct: `E2E_NETWORK`
156
- (physical chain) vs the app network (testnet/mainnet UI mode; localnet borrows testnet mode with
157
- the RPC pointed at the local node). Mainnet is fail-safe: aborts unless `E2E_MAINNET_CONFIRM=1`.
158
- `scripts/e2e-browser.mjs` is a thin `E2E_NETWORK=localnet` wrapper; `scripts/e2e-walrus-browser.mjs`
159
- (testnet icon upload) uses the E2E-only `window.__getSuiClient` hook in `src/main.ts`. Testnet/
160
- mainnet are **manual only** — never in automatic CI (see the README launch runbook). The
161
- `.github/workflows/token-deployer-e2e.yml` `workflow_dispatch` job is the gated manual runner.
162
-
163
- ## Docs
164
-
165
- TSDoc on every exported symbol in `src/lib`, `src/composables`, and `src/config.ts`;
166
- `npm run docs` renders a TypeDoc site to `docs/api/` (config: [typedoc.json](typedoc.json)).
package/Dockerfile DELETED
@@ -1,96 +0,0 @@
1
- # ── build stage ───────────────────────────────────────────────────────────────
2
- # Standalone build — the Docker context is this repo root. All @meddleware/*
3
- # dependencies resolve from the npm registry, so they must be published before
4
- # this image is built.
5
- #
6
- # docker build \
7
- # --build-arg VITE_NETWORK=testnet \
8
- # --build-arg VITE_FEE_TREASURY_TESTNET=0x... \
9
- # --build-arg VITE_FEE_TREASURY_MAINNET=0x... \
10
- # -t token-deployer-ui:<tag> .
11
- #
12
- # Build args (VITE_* are baked into the static bundle at build time):
13
- # VITE_NETWORK — "testnet" | "mainnet" (default: testnet)
14
- # VITE_FEE_TREASURY_TESTNET — operator treasury for testnet (REQUIRED — build fails without it)
15
- # VITE_FEE_TREASURY_MAINNET — operator treasury for mainnet (REQUIRED — build fails without it)
16
- # VITE_FEE_MIST — fee in MIST (optional, default 1000000000)
17
- # VITE_WALRUS_RELAY_TESTNET — operator relay URL for testnet (optional)
18
- # VITE_WALRUS_RELAY_MAINNET — operator relay URL for mainnet (optional)
19
- # VITE_WALRUS_RPC_TESTNET — gRPC fullnode for Walrus testnet (optional)
20
- # VITE_WALRUS_RPC_MAINNET — gRPC fullnode for Walrus mainnet (optional)
21
- # VITE_RPC_TESTNET / VITE_RPC_MAINNET — override gRPC fullnode URLs (optional)
22
- # VITE_ACCESS_GATE_ID_{NET} — operator's Gate shared object ID (optional)
23
- # VITE_ACCESS_GATE_NFT_TYPE_{NET} — access NFT type (optional)
24
- # VITE_ACCESS_GATE_SOULBOUND_{NET} — "true" if soulbound (optional)
25
- # VITE_ACCESS_GATE_PRICE_MIST_{NET} — purchase price in MIST (optional)
26
- # VITE_WALRUS_MAX_TIP_MIST — max relay tip cap in MIST (optional)
27
- # VITE_PUBLIC_URL — canonical origin for OG/JSON-LD (optional)
28
- #
29
- # .env.production is gitignored — treasury addresses must be supplied via build args.
30
- FROM node:24-slim AS build
31
-
32
- WORKDIR /app
33
-
34
- COPY package.json package-lock.json ./
35
-
36
- RUN npm ci
37
-
38
- COPY . .
39
-
40
- ARG VITE_NETWORK=testnet
41
- ARG VITE_FEE_TREASURY_TESTNET
42
- ARG VITE_FEE_TREASURY_MAINNET
43
- ARG VITE_FEE_MIST
44
- ARG VITE_WALRUS_RELAY_TESTNET
45
- ARG VITE_WALRUS_RELAY_MAINNET
46
- ARG VITE_WALRUS_RPC_TESTNET
47
- ARG VITE_WALRUS_RPC_MAINNET
48
- ARG VITE_RPC_TESTNET
49
- ARG VITE_RPC_MAINNET
50
- ARG VITE_ACCESS_GATE_ID_TESTNET
51
- ARG VITE_ACCESS_GATE_NFT_TYPE_TESTNET
52
- ARG VITE_ACCESS_GATE_SOULBOUND_TESTNET
53
- ARG VITE_ACCESS_GATE_PRICE_MIST_TESTNET
54
- ARG VITE_ACCESS_GATE_ID_MAINNET
55
- ARG VITE_ACCESS_GATE_NFT_TYPE_MAINNET
56
- ARG VITE_ACCESS_GATE_SOULBOUND_MAINNET
57
- ARG VITE_ACCESS_GATE_PRICE_MIST_MAINNET
58
- ARG VITE_WALRUS_MAX_TIP_MIST
59
- ARG VITE_PUBLIC_URL
60
-
61
- ENV VITE_NETWORK=${VITE_NETWORK} \
62
- VITE_FEE_TREASURY_TESTNET=${VITE_FEE_TREASURY_TESTNET} \
63
- VITE_FEE_TREASURY_MAINNET=${VITE_FEE_TREASURY_MAINNET} \
64
- VITE_FEE_MIST=${VITE_FEE_MIST} \
65
- VITE_WALRUS_RELAY_TESTNET=${VITE_WALRUS_RELAY_TESTNET} \
66
- VITE_WALRUS_RELAY_MAINNET=${VITE_WALRUS_RELAY_MAINNET} \
67
- VITE_WALRUS_RPC_TESTNET=${VITE_WALRUS_RPC_TESTNET} \
68
- VITE_WALRUS_RPC_MAINNET=${VITE_WALRUS_RPC_MAINNET} \
69
- VITE_RPC_TESTNET=${VITE_RPC_TESTNET} \
70
- VITE_RPC_MAINNET=${VITE_RPC_MAINNET} \
71
- VITE_ACCESS_GATE_ID_TESTNET=${VITE_ACCESS_GATE_ID_TESTNET} \
72
- VITE_ACCESS_GATE_NFT_TYPE_TESTNET=${VITE_ACCESS_GATE_NFT_TYPE_TESTNET} \
73
- VITE_ACCESS_GATE_SOULBOUND_TESTNET=${VITE_ACCESS_GATE_SOULBOUND_TESTNET} \
74
- VITE_ACCESS_GATE_PRICE_MIST_TESTNET=${VITE_ACCESS_GATE_PRICE_MIST_TESTNET} \
75
- VITE_ACCESS_GATE_ID_MAINNET=${VITE_ACCESS_GATE_ID_MAINNET} \
76
- VITE_ACCESS_GATE_NFT_TYPE_MAINNET=${VITE_ACCESS_GATE_NFT_TYPE_MAINNET} \
77
- VITE_ACCESS_GATE_SOULBOUND_MAINNET=${VITE_ACCESS_GATE_SOULBOUND_MAINNET} \
78
- VITE_ACCESS_GATE_PRICE_MIST_MAINNET=${VITE_ACCESS_GATE_PRICE_MIST_MAINNET} \
79
- VITE_WALRUS_MAX_TIP_MIST=${VITE_WALRUS_MAX_TIP_MIST} \
80
- VITE_PUBLIC_URL=${VITE_PUBLIC_URL}
81
-
82
- RUN npm run build
83
-
84
- # ── runtime stage ─────────────────────────────────────────────────────────────
85
- # static-server is a minimal Go binary image — no shell, no package manager.
86
- # SPA_FALLBACK serves index.html for any extensionless path (Vue Router history mode).
87
- # CACHE_IMMUTABLE_PREFIX matches the /assets/ directory Vite emits with content hashes.
88
- FROM quay.io/meddleware-org/static-server:0.1.1
89
-
90
- COPY --from=build /app/dist /app/public
91
-
92
- ENV SERVE_DIR=/app/public \
93
- SPA_FALLBACK=true \
94
- CACHE_IMMUTABLE_PREFIX=/assets/
95
-
96
- EXPOSE 8080
package/eslint.config.ts DELETED
@@ -1,63 +0,0 @@
1
- import { globalIgnores } from 'eslint/config'
2
- import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
3
- import pluginVue from 'eslint-plugin-vue'
4
- import pluginA11y from 'eslint-plugin-vuejs-accessibility'
5
-
6
- // Flat ESLint config: layers vue-a11y (WAI-ARIA linting for templates) on top of
7
- // the standard Vue + TypeScript recommended rules, so accessibility regressions
8
- // are caught in CI.
9
- export default defineConfigWithVueTs(
10
- {
11
- name: 'token-deployer-ui/files-to-lint',
12
- files: ['**/*.{vue,ts,mts,tsx}'],
13
- },
14
-
15
- globalIgnores(['**/dist/**', '**/coverage/**', '**/*.d.ts', 'docs/api/**']),
16
-
17
- ...pluginVue.configs['flat/essential'],
18
- ...pluginA11y.configs['flat/recommended'],
19
- vueTsConfigs.recommended,
20
-
21
- {
22
- name: 'token-deployer-ui/overrides',
23
- rules: {
24
- // Accept both valid label-association patterns: a label wrapping its
25
- // control (nesting) or a label[for] pointing at a control[id]. UiSelect renders a native
26
- // <select>, so a label nesting it is labelling a control.
27
- 'vuejs-accessibility/label-has-for': [
28
- 'error',
29
- { required: { some: ['nesting', 'id'] }, controlComponents: ['UiSelect'] },
30
- ],
31
- // UiFormField renders the <label for> for the control in its default slot.
32
- 'vuejs-accessibility/form-control-has-label': ['error', { labelComponents: ['UiFormField'] }],
33
- // role="list" on styled lists is a deliberate Safari/VoiceOver workaround: WebKit drops
34
- // list semantics when list-style is removed, so the explicit role stays.
35
- 'vuejs-accessibility/no-redundant-roles': 'off',
36
- // Underscore-prefixed args/vars are an intentional "unused" marker.
37
- '@typescript-eslint/no-unused-vars': [
38
- 'error',
39
- { argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
40
- ],
41
- },
42
- },
43
-
44
- {
45
- // Tests use deliberately loose typing for mocks/stubs.
46
- name: 'token-deployer-ui/test-overrides',
47
- files: ['**/*.{test,spec}.{ts,tsx}', 'tests/**', 'e2e/**'],
48
- rules: {
49
- '@typescript-eslint/no-explicit-any': 'off',
50
- },
51
- },
52
-
53
- {
54
- // ConfigForm intentionally edits a parent-owned reactive FormModel in place
55
- // (the parent passes `:form` and reads the same object back). Converting to
56
- // defineModel is deferred; the in-place mutation is the current contract.
57
- name: 'token-deployer-ui/config-form',
58
- files: ['src/components/ConfigForm.vue'],
59
- rules: {
60
- 'vue/no-mutating-props': 'off',
61
- },
62
- },
63
- )
package/index.html DELETED
@@ -1,22 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <link rel="icon" href="/favicon.svg" type="image/svg+xml">
6
- <link rel="icon" href="/favicon.ico" sizes="any">
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
- <title>Token Deployer · MeddleWare</title>
9
- <meta name="description" content="Create your own Sui coin in the browser — your wallet signs and pays gas, nothing is compiled or signed on a server, and you keep the full, verifiable source package.">
10
- <link rel="canonical" href="%VITE_PUBLIC_URL%/">
11
- <meta property="og:type" content="website">
12
- <meta property="og:title" content="Token Deployer · MeddleWare">
13
- <meta property="og:description" content="Create your own Sui coin in the browser — no server, no custody, full source included.">
14
- <meta property="og:url" content="%VITE_PUBLIC_URL%/">
15
- <meta property="og:image" content="%VITE_PUBLIC_URL%/og-image.png">
16
- <meta name="twitter:card" content="summary_large_image">
17
- </head>
18
- <body>
19
- <div id="app"></div>
20
- <script type="module" src="/src/main.ts"></script>
21
- </body>
22
- </html>
@@ -1,30 +0,0 @@
1
- import { defineConfig, devices } from '@playwright/test'
2
-
3
- // Mocked-RPC UI e2e. Standardised on Playwright (robust; replaces the former
4
- // Cypress mocked suite, which exits SIGILL in the sandbox). The app is built with
5
- // VITE_E2E=1 so main.ts registers the mock wallet + fetch mock (tree-shaken from
6
- // prod). Real-chain e2e stays in scripts/e2e-deploy.mjs (npm run e2e:localnet…).
7
- const PORT = 4173
8
-
9
- export default defineConfig({
10
- testDir: './e2e',
11
- fullyParallel: true,
12
- forbidOnly: !!process.env.CI,
13
- retries: process.env.CI ? 2 : 0,
14
- reporter: 'list',
15
- use: {
16
- baseURL: `http://localhost:${PORT}`,
17
- viewport: { width: 1280, height: 800 },
18
- trace: 'on-first-retry',
19
- },
20
- webServer: {
21
- command: `npm run build:e2e && npm run preview -- --port ${PORT} --strictPort`,
22
- url: `http://localhost:${PORT}/`,
23
- reuseExistingServer: !process.env.CI,
24
- timeout: 180_000,
25
- },
26
- projects: [
27
- { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
28
- { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
29
- ],
30
- })
package/postcss.config.js DELETED
@@ -1,8 +0,0 @@
1
- // Autoprefixer runs over the library's shipped CSS (base.css) during `vite build`,
2
- // using the `browserslist` field in package.json as the target. Consumers therefore
3
- // receive vendor-prefixed component CSS without needing their own prefixing step.
4
- import autoprefixer from 'autoprefixer'
5
-
6
- export default {
7
- plugins: [autoprefixer()],
8
- }
package/public/CNAME DELETED
@@ -1 +0,0 @@
1
- sui-token-deployer.meddleware.co.uk
package/public/_headers DELETED
@@ -1,12 +0,0 @@
1
- # Cloudflare Pages headers. Security baseline; connect-src stays broad because
2
- # wallet extensions, Walrus relays, and per-network Sui RPCs vary.
3
- /*
4
- X-Content-Type-Options: nosniff
5
- Referrer-Policy: strict-origin-when-cross-origin
6
- X-Frame-Options: DENY
7
- Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=()
8
- Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' https: wss:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
9
-
10
- # Long-cache hashed build assets.
11
- /assets/*
12
- Cache-Control: public, max-age=31536000, immutable
package/public/_redirects DELETED
@@ -1 +0,0 @@
1
- /* /index.html 200
Binary file
@@ -1,5 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" role="img" aria-label="Token Deployer">
2
- <circle cx="16" cy="16" r="15" fill="#2f6feb"/>
3
- <circle cx="16" cy="16" r="15" fill="none" stroke="#1b4fc0" stroke-width="2"/>
4
- <text x="16" y="21" font-family="system-ui, sans-serif" font-size="14" font-weight="700" fill="#fff" text-anchor="middle">S</text>
5
- </svg>
Binary file
package/public/robots.txt DELETED
@@ -1,3 +0,0 @@
1
- User-agent: *
2
- Allow: /
3
- Sitemap: https://sui-token-deployer.meddleware.co.uk/sitemap.xml
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
- <url>
4
- <loc>https://sui-token-deployer.meddleware.co.uk/</loc>
5
- <changefreq>monthly</changefreq>
6
- <priority>1.0</priority>
7
- </url>
8
- </urlset>
@@ -1,15 +0,0 @@
1
- // Thin wrapper: localnet deploy e2e. The real implementation is the network-parametrized
2
- // `e2e-deploy.mjs`; this just pins E2E_NETWORK=localnet so the historical entry point and its
3
- // localnet defaults (fresh keypair + faucet, 0xfee… treasury, 1 SUI fee assertion) keep working.
4
- //
5
- // Prereq (as before): build the app with the testnet RPC pointed at the local node and a
6
- // treasury set, then serve dist on APP_URL (default http://localhost:4173):
7
- // VITE_RPC_TESTNET=http://127.0.0.1:9000 VITE_FEE_TREASURY_TESTNET=<addr> vite build
8
- //
9
- // Equivalent to `E2E_NETWORK=localnet node scripts/e2e-deploy.mjs` — or just `npm run e2e:localnet`.
10
-
11
- process.env.E2E_NETWORK = 'localnet'
12
- // Preserve the legacy FEE_ADDR override name for anyone still setting it.
13
- if (process.env.FEE_ADDR && !process.env.E2E_FEE_ADDR) process.env.E2E_FEE_ADDR = process.env.FEE_ADDR
14
-
15
- await import('./e2e-deploy.mjs')