@meddleware/dashboard 0.1.2 → 0.1.4

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.
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@meddleware/dashboard",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Meddleware tools hub — Vue 3 SPA listing hosted services (Walrus, Access Gate) with white-label deploy options.",
5
- "author": "MeddleWare <meddleware@proton.me>",
5
+ "author": "Meddleware <dev@meddleware.co.uk>",
6
6
  "license": "0BSD",
7
7
  "repository": {
8
8
  "type": "git",
@@ -28,10 +28,15 @@
28
28
  "dependencies": {
29
29
  "@meddleware/design-tokens": "^0.1.2",
30
30
  "@meddleware/ui": "^0.1.6",
31
+ "@meddleware/wallet-adapter": "^0.0.1",
32
+ "@meddleware/walrus-ui": "^0.1.4",
31
33
  "pinia": "^4.0.2",
32
34
  "vue": "^3.5.40",
33
35
  "vue-router": "^5.2.0"
34
36
  },
37
+ "overrides": {
38
+ "@mysten/sui": "2.17.0"
39
+ },
35
40
  "devDependencies": {
36
41
  "@types/node": "~24.12.2",
37
42
  "@vitejs/plugin-vue": "^6.0.8",
package/src/App.vue CHANGED
@@ -2,18 +2,34 @@
2
2
  import { computed } from 'vue'
3
3
  import { useRoute, RouterView } from 'vue-router'
4
4
  import {
5
- AppHeader, AppSidebar, AppFooter,
5
+ AppHeader, AppSidebar,
6
6
  ColorModeControl, SidebarItem, StatusWidget,
7
7
  useColorMode,
8
8
  } from '@meddleware/ui'
9
+ import { useWallet } from '@meddleware/wallet-adapter'
9
10
 
10
11
  const { mode, set } = useColorMode('dark')
11
12
  const route = useRoute()
12
- const year = new Date().getFullYear()
13
13
 
14
14
  const isWalrus = computed(() => route.path === '/walrus')
15
15
  const isAccessGate = computed(() => route.path === '/access-gate')
16
16
  const isSealedStorage = computed(() => route.path === '/sealed-storage')
17
+
18
+ // The dashboard hosts the single shared wallet connection for every inline tool view. It
19
+ // requests the superset of features the tools need so the connect control only offers wallets
20
+ // capable of every operation; individual tools still feature-guard at call time.
21
+ const { wallets, account, connect, disconnect, connecting } = useWallet({
22
+ requiredFeatures: ['sui:signTransaction', 'sui:signPersonalMessage'],
23
+ })
24
+
25
+ async function onConnect(): Promise<void> {
26
+ const w = wallets.value[0]
27
+ if (w) await connect(w)
28
+ }
29
+
30
+ function shortAddr(addr: string): string {
31
+ return `${addr.slice(0, 8)}…${addr.slice(-4)}`
32
+ }
17
33
  </script>
18
34
 
19
35
  <template>
@@ -24,6 +40,21 @@ const isSealedStorage = computed(() => route.path === '/sealed-storage')
24
40
  <span>Meddleware</span>
25
41
  </template>
26
42
  <template #actions>
43
+ <span v-if="account" class="wallet-addr" :title="account.address">
44
+ {{ shortAddr(account.address) }}
45
+ </span>
46
+ <button v-if="account" type="button" class="wallet-btn" @click="disconnect">
47
+ Disconnect
48
+ </button>
49
+ <button
50
+ v-else
51
+ type="button"
52
+ class="wallet-btn"
53
+ :disabled="!wallets.length || connecting"
54
+ @click="onConnect"
55
+ >
56
+ {{ wallets.length ? (connecting ? 'Connecting…' : 'Connect wallet') : 'No wallet' }}
57
+ </button>
27
58
  <StatusWidget />
28
59
  <ColorModeControl :model-value="mode" @update:model-value="set" />
29
60
  </template>
@@ -46,15 +77,56 @@ const isSealedStorage = computed(() => route.path === '/sealed-storage')
46
77
  <main class="app-shell__main">
47
78
  <RouterView />
48
79
  </main>
49
-
50
- <AppFooter class="app-shell__footer" variant="transparent">
51
- <span>&copy; {{ year }} Meddleware</span>
52
- </AppFooter>
53
80
  </div>
54
81
  </template>
55
82
 
56
83
  <style scoped>
84
+ .app-shell {
85
+ display: grid;
86
+ grid-template-columns: var(--mw-sidebar-width, 240px) 1fr;
87
+ grid-template-rows: var(--mw-header-height, 56px) 1fr;
88
+ height: 100vh;
89
+ overflow: hidden;
90
+ }
91
+
92
+ .app-shell__header {
93
+ grid-column: 1 / -1;
94
+ }
95
+
96
+ .app-shell__sidebar {
97
+ height: 100%;
98
+ overflow-y: auto;
99
+ }
100
+
101
+ .app-shell__main {
102
+ /* Inline tool views can exceed the viewport — scroll the main area internally
103
+ (the shell itself stays fixed at 100vh). */
104
+ overflow-y: auto;
105
+ height: 100%;
106
+ }
107
+
57
108
  .brand-mark {
58
109
  color: var(--gold);
59
110
  }
111
+
112
+ .wallet-addr {
113
+ font-family: monospace;
114
+ font-size: 0.85rem;
115
+ color: var(--muted);
116
+ }
117
+
118
+ .wallet-btn {
119
+ background: none;
120
+ border: 1px solid var(--border);
121
+ border-radius: 8px;
122
+ padding: 0.35rem 0.75rem;
123
+ cursor: pointer;
124
+ color: var(--text);
125
+ font-size: 0.85rem;
126
+ }
127
+
128
+ .wallet-btn:disabled {
129
+ opacity: 0.5;
130
+ cursor: not-allowed;
131
+ }
60
132
  </style>
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ defineProps<{ src: string; title: string }>()
3
+ </script>
4
+
5
+ <template>
6
+ <iframe
7
+ :src="src"
8
+ :title="title"
9
+ class="tool-frame"
10
+ allow="camera; clipboard-read; clipboard-write"
11
+ />
12
+ </template>
13
+
14
+ <style scoped>
15
+ .tool-frame {
16
+ display: block;
17
+ width: 100%;
18
+ height: 100%;
19
+ border: none;
20
+ }
21
+ </style>
@@ -1,16 +1,20 @@
1
1
  import { createRouter, createWebHistory } from 'vue-router'
2
2
  import Home from '../views/Home.vue'
3
- import WalrusPage from '../views/WalrusPage.vue'
4
- import AccessGatePage from '../views/AccessGatePage.vue'
5
- import SealedStoragePage from '../views/SealedStoragePage.vue'
3
+ import ToolPage from '../views/ToolPage.vue'
6
4
 
5
+ // Walrus renders inline via the component exported from @meddleware/walrus-ui (no iframe).
6
+ // It shares the dashboard's wallet connection through the @meddleware/wallet-adapter singleton.
7
+ // Access Gate and Sealed Storage remain on the interim iframe path until their phases land.
7
8
  const router = createRouter({
8
9
  history: createWebHistory(import.meta.env.BASE_URL),
9
10
  routes: [
10
11
  { path: '/', component: Home },
11
- { path: '/walrus', component: WalrusPage },
12
- { path: '/access-gate', component: AccessGatePage },
13
- { path: '/sealed-storage', component: SealedStoragePage },
12
+ {
13
+ path: '/walrus',
14
+ component: () => import('@meddleware/walrus-ui').then((m) => m.WalrusView),
15
+ },
16
+ { path: '/access-gate', component: ToolPage, props: { src: 'https://sui-access-gate.meddleware.co.uk/?embedded=1', title: 'Access Gate' } },
17
+ { path: '/sealed-storage', component: ToolPage, props: { src: 'https://sui-seal.meddleware.co.uk/?embedded=1', title: 'Sealed Storage' } },
14
18
  ],
15
19
  })
16
20
 
@@ -16,43 +16,16 @@ const router = useRouter()
16
16
  <UiCard class="tool-card" @click="router.push('/walrus')">
17
17
  <h2>🗄 Walrus</h2>
18
18
  <p>Upload and manage blobs on Walrus decentralised storage. NFT-gated relay, wallet-connected, no backend required.</p>
19
- <a
20
- href="https://sui-walrus.meddleware.co.uk"
21
- target="_blank"
22
- rel="noopener"
23
- class="launch-link"
24
- @click.stop
25
- >
26
- Launch →
27
- </a>
28
19
  </UiCard>
29
20
 
30
21
  <UiCard class="tool-card" @click="router.push('/access-gate')">
31
22
  <h2>🔐 Access Gate</h2>
32
23
  <p>Create and manage NFT-gated access controls on Sui. Commission-enforced on-chain, no server required.</p>
33
- <a
34
- href="https://sui-access-gate.meddleware.co.uk"
35
- target="_blank"
36
- rel="noopener"
37
- class="launch-link"
38
- @click.stop
39
- >
40
- Launch →
41
- </a>
42
24
  </UiCard>
43
25
 
44
26
  <UiCard class="tool-card" @click="router.push('/sealed-storage')">
45
27
  <h2>🔒 Sealed Storage</h2>
46
28
  <p>Client-side encrypted, access-gated storage: seal a file, store it on Walrus, and gate decryption on-chain (NFT pass, time-lock, and more). Testnet — mainnet pending.</p>
47
- <a
48
- href="https://sui-seal.meddleware.co.uk"
49
- target="_blank"
50
- rel="noopener"
51
- class="launch-link"
52
- @click.stop
53
- >
54
- Launch →
55
- </a>
56
29
  </UiCard>
57
30
  </div>
58
31
  </div>
@@ -72,12 +45,4 @@ h1 { margin-top: 0; }
72
45
  .tool-card { cursor: pointer; }
73
46
  .tool-card h2 { margin-top: 0; }
74
47
 
75
- .launch-link {
76
- display: inline-block;
77
- margin-top: 0.5rem;
78
- color: var(--accent);
79
- text-decoration: none;
80
- font-weight: 500;
81
- }
82
- .launch-link:hover { text-decoration: underline; }
83
48
  </style>
@@ -0,0 +1,9 @@
1
+ <script setup lang="ts">
2
+ import ToolFrame from '../components/ToolFrame.vue'
3
+
4
+ defineProps<{ src: string; title: string }>()
5
+ </script>
6
+
7
+ <template>
8
+ <ToolFrame :src="src" :title="title" />
9
+ </template>
package/vite.config.ts CHANGED
@@ -4,4 +4,9 @@ import vue from '@vitejs/plugin-vue'
4
4
  // @meddleware/* resolve from node_modules (published packages — no monorepo aliases).
5
5
  export default defineConfig({
6
6
  plugins: [vue()],
7
+ optimizeDeps: {
8
+ // The Walrus wasm client is dynamically imported inside the inline WalrusView upload flow;
9
+ // keep it out of the eager dep-optimization graph so it stays a lazy chunk.
10
+ exclude: ['@mysten/walrus', '@mysten/walrus-wasm'],
11
+ },
7
12
  })
@@ -1,83 +0,0 @@
1
- <script setup lang="ts">
2
- import { UiCard } from '@meddleware/ui'
3
- </script>
4
-
5
- <template>
6
- <div class="feature-page">
7
- <h1>🔐 Access Gate</h1>
8
-
9
- <UiCard class="section">
10
- <h2>Overview</h2>
11
- <p>
12
- Access Gate is an on-chain NFT access control system on Sui. Operators deploy a gate
13
- smart contract that issues soulbound or transferable NFT passes; the gate enforces a
14
- platform commission (20 bps) on every pass purchase, routed directly on-chain. The
15
- Meddleware Access Gate console lets you create gates, configure pricing, and monitor
16
- your gate's activity — all from a browser wallet, with no backend required.
17
- </p>
18
- </UiCard>
19
-
20
- <UiCard class="section">
21
- <h2>Launch</h2>
22
- <p>Use the hosted Meddleware Access Gate console — no installation required.</p>
23
- <a
24
- href="https://sui-access-gate.meddleware.co.uk"
25
- target="_blank"
26
- rel="noopener"
27
- class="launch-btn"
28
- >
29
- Open Access Gate →
30
- </a>
31
- </UiCard>
32
-
33
- <UiCard class="section section--secondary">
34
- <h2>White-label</h2>
35
- <p>
36
- Deploy a branded version of the Access Gate console for your own project. The
37
- <code>access-gate-ui</code> Docker image is a standalone Vue 3 SPA — run it behind
38
- your own subdomain and point users at your specific gate ID. The commission enforcement
39
- is in the smart contract, so any gate created through your interface still routes 20 bps
40
- to Meddleware automatically.
41
- </p>
42
- <p class="note">
43
- Detailed deployment instructions will be available at <code>dev.meddleware.co.uk</code>.
44
- </p>
45
- </UiCard>
46
- </div>
47
- </template>
48
-
49
- <style scoped>
50
- .feature-page { max-width: 760px; }
51
- h1 { margin-top: 0; }
52
-
53
- .section { margin-bottom: 1.25rem; }
54
- .section h2 { margin-top: 0; }
55
-
56
- .section--secondary { opacity: 0.9; }
57
- .section--secondary h2 { font-size: 1rem; }
58
-
59
- .launch-btn {
60
- display: inline-block;
61
- margin-top: 0.25rem;
62
- padding: 0.55rem 1.2rem;
63
- border-radius: var(--mw-radius, 10px);
64
- background: var(--accent);
65
- color: #fff;
66
- text-decoration: none;
67
- font-weight: 600;
68
- }
69
- .launch-btn:hover { opacity: 0.88; }
70
-
71
- code {
72
- font-size: 0.85em;
73
- background: color-mix(in srgb, currentColor 10%, transparent);
74
- padding: 0.1em 0.35em;
75
- border-radius: 4px;
76
- }
77
-
78
- .note {
79
- margin-top: 0.75rem;
80
- font-size: 0.85rem;
81
- color: var(--muted);
82
- }
83
- </style>
@@ -1,99 +0,0 @@
1
- <script setup lang="ts">
2
- import { UiCard } from '@meddleware/ui'
3
- </script>
4
-
5
- <template>
6
- <div class="feature-page">
7
- <h1>🔒 Sealed Storage <span class="badge">Testnet · mainnet pending</span></h1>
8
-
9
- <UiCard class="section">
10
- <h2>Overview</h2>
11
- <p>
12
- Sealed Storage composes three primitives into one: encrypt a file in your browser with
13
- <strong>Seal</strong> (threshold identity-based encryption), store the ciphertext on
14
- <strong>Walrus</strong>, and gate decryption with an on-chain <strong>access policy</strong>.
15
- Decryption keys are released by a committee of independent key servers only when the policy is
16
- satisfied — no server ever holds your data or keys. Policies are modular: gate on an
17
- <strong>access-gate NFT</strong>, a <strong>time-lock</strong>, and more over time.
18
- </p>
19
- </UiCard>
20
-
21
- <UiCard class="section">
22
- <h2>Launch</h2>
23
- <p>Use the hosted Meddleware Sealed Storage app (testnet).</p>
24
- <a
25
- href="https://sui-seal.meddleware.co.uk"
26
- target="_blank"
27
- rel="noopener"
28
- class="launch-btn"
29
- >
30
- Open Sealed Storage →
31
- </a>
32
- <p class="note">
33
- Mainnet is pending: Seal committee mode is currently testnet-only. The app will enable mainnet
34
- automatically once it ships.
35
- </p>
36
- </UiCard>
37
-
38
- <UiCard class="section section--secondary">
39
- <h2>White-label</h2>
40
- <p>
41
- Deploy your own branded Sealed Storage with the <code>seal-ui</code> Docker image: set your
42
- network, policy package, key-server committee, and Walrus endpoints via build-time VITE args.
43
- The policy contracts (<code>seal-policies-sui</code>) and client
44
- (<code>@meddleware/seal-client</code>) are reusable — add your own policy type as a drop-in
45
- Move module + client provider.
46
- </p>
47
- <p class="note">
48
- Detailed deployment instructions will be available at <code>dev.meddleware.co.uk</code>.
49
- </p>
50
- </UiCard>
51
- </div>
52
- </template>
53
-
54
- <style scoped>
55
- .feature-page { max-width: 760px; }
56
- h1 { margin-top: 0; }
57
-
58
- .badge {
59
- font-size: 0.6em;
60
- vertical-align: middle;
61
- text-transform: uppercase;
62
- letter-spacing: 0.04em;
63
- padding: 0.2em 0.6em;
64
- border-radius: 999px;
65
- background: color-mix(in srgb, var(--gold, #d29922) 22%, transparent);
66
- color: var(--text);
67
- }
68
-
69
- .section { margin-bottom: 1.25rem; }
70
- .section h2 { margin-top: 0; }
71
-
72
- .section--secondary { opacity: 0.9; }
73
- .section--secondary h2 { font-size: 1rem; }
74
-
75
- .launch-btn {
76
- display: inline-block;
77
- margin-top: 0.25rem;
78
- padding: 0.55rem 1.2rem;
79
- border-radius: var(--mw-radius, 10px);
80
- background: var(--accent);
81
- color: #fff;
82
- text-decoration: none;
83
- font-weight: 600;
84
- }
85
- .launch-btn:hover { opacity: 0.88; }
86
-
87
- code {
88
- font-size: 0.85em;
89
- background: color-mix(in srgb, currentColor 10%, transparent);
90
- padding: 0.1em 0.35em;
91
- border-radius: 4px;
92
- }
93
-
94
- .note {
95
- margin-top: 0.75rem;
96
- font-size: 0.85rem;
97
- color: var(--muted);
98
- }
99
- </style>
@@ -1,88 +0,0 @@
1
- <script setup lang="ts">
2
- import { UiCard } from '@meddleware/ui'
3
- </script>
4
-
5
- <template>
6
- <div class="feature-page">
7
- <h1>🗄 Walrus</h1>
8
-
9
- <UiCard class="section">
10
- <h2>Overview</h2>
11
- <p>
12
- Walrus is a decentralised blob storage network built on Sui. The Meddleware Walrus app
13
- lets you upload arbitrary files, manage your owned blobs, and extend their storage lifetime
14
- — all from your browser wallet. Access is controlled by an on-chain NFT gate: the relay tip
15
- is paid only after gate verification, keeping the relay open to legitimate holders while
16
- preventing spam.
17
- </p>
18
- </UiCard>
19
-
20
- <UiCard class="section">
21
- <h2>Launch</h2>
22
- <p>Use the hosted Meddleware Walrus app — no installation required.</p>
23
- <a
24
- href="https://sui-walrus.meddleware.co.uk"
25
- target="_blank"
26
- rel="noopener"
27
- class="launch-btn"
28
- >
29
- Open Walrus →
30
- </a>
31
- </UiCard>
32
-
33
- <UiCard class="section section--secondary">
34
- <h2>White-label</h2>
35
- <p>
36
- Run your own branded Walrus upload experience. The <code>walrus-ui</code> Docker image
37
- accepts VITE build args baked at build time — set your relay URL, network, and access
38
- gate IDs, then deploy the image behind your own subdomain.
39
- </p>
40
- <p>
41
- You will also need your own NFT gate (deployed via Access Gate) and a running relay
42
- Worker (nft-gate Cloudflare Worker pointing at a Walrus upload relay origin). The
43
- commission enforcement (20 bps) is hard-coded in the
44
- <code>@meddleware/walrus-relay</code> library constants and applies to all relays,
45
- regardless of who operates them.
46
- </p>
47
- <p class="note">
48
- Detailed deployment instructions will be available at <code>dev.meddleware.co.uk</code>.
49
- </p>
50
- </UiCard>
51
- </div>
52
- </template>
53
-
54
- <style scoped>
55
- .feature-page { max-width: 760px; }
56
- h1 { margin-top: 0; }
57
-
58
- .section { margin-bottom: 1.25rem; }
59
- .section h2 { margin-top: 0; }
60
-
61
- .section--secondary { opacity: 0.9; }
62
- .section--secondary h2 { font-size: 1rem; }
63
-
64
- .launch-btn {
65
- display: inline-block;
66
- margin-top: 0.25rem;
67
- padding: 0.55rem 1.2rem;
68
- border-radius: var(--mw-radius, 10px);
69
- background: var(--accent);
70
- color: #fff;
71
- text-decoration: none;
72
- font-weight: 600;
73
- }
74
- .launch-btn:hover { opacity: 0.88; }
75
-
76
- code {
77
- font-size: 0.85em;
78
- background: color-mix(in srgb, currentColor 10%, transparent);
79
- padding: 0.1em 0.35em;
80
- border-radius: 4px;
81
- }
82
-
83
- .note {
84
- margin-top: 0.75rem;
85
- font-size: 0.85rem;
86
- color: var(--muted);
87
- }
88
- </style>