@meddleware/dashboard 0.1.1
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/index.html +13 -0
- package/package.json +45 -0
- package/src/App.vue +60 -0
- package/src/env.d.ts +7 -0
- package/src/main.ts +20 -0
- package/src/router/index.ts +17 -0
- package/src/styles.css +49 -0
- package/src/views/AccessGatePage.vue +83 -0
- package/src/views/Home.vue +83 -0
- package/src/views/SealedStoragePage.vue +99 -0
- package/src/views/WalrusPage.vue +88 -0
- package/tsconfig.json +18 -0
- package/vite.config.ts +7 -0
package/index.html
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<link rel="icon" href="/favicon.ico">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Meddleware</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="app"></div>
|
|
11
|
+
<script type="module" src="/src/main.ts"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@meddleware/dashboard",
|
|
3
|
+
"version": "0.1.1",
|
|
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>",
|
|
6
|
+
"license": "0BSD",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/meddleware-org/dashboard.git"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"files": [
|
|
13
|
+
"src",
|
|
14
|
+
"index.html",
|
|
15
|
+
"vite.config.ts",
|
|
16
|
+
"tsconfig.json",
|
|
17
|
+
"CHANGELOG.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"dev": "vite",
|
|
21
|
+
"build": "vue-tsc --noEmit && vite build",
|
|
22
|
+
"preview": "vite preview",
|
|
23
|
+
"type-check": "vue-tsc --noEmit"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@meddleware/design-tokens": "^0.1.2",
|
|
30
|
+
"@meddleware/ui": "^0.1.5",
|
|
31
|
+
"pinia": "^4.0.2",
|
|
32
|
+
"vue": "^3.5.40",
|
|
33
|
+
"vue-router": "^5.2.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "~24.12.2",
|
|
37
|
+
"@vitejs/plugin-vue": "^6.0.8",
|
|
38
|
+
"typescript": "~6.0.0",
|
|
39
|
+
"vite": "^8.1.5",
|
|
40
|
+
"vue-tsc": "~3.3.0"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": "^22.18.0 || >=24.12.0"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/App.vue
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useRoute, RouterView } from 'vue-router'
|
|
4
|
+
import {
|
|
5
|
+
AppHeader, AppSidebar, AppFooter,
|
|
6
|
+
ColorModeControl, SidebarItem, StatusWidget,
|
|
7
|
+
useColorMode,
|
|
8
|
+
} from '@meddleware/ui'
|
|
9
|
+
|
|
10
|
+
const { mode, set } = useColorMode('dark')
|
|
11
|
+
const route = useRoute()
|
|
12
|
+
const year = new Date().getFullYear()
|
|
13
|
+
|
|
14
|
+
const isWalrus = computed(() => route.path === '/walrus')
|
|
15
|
+
const isAccessGate = computed(() => route.path === '/access-gate')
|
|
16
|
+
const isSealedStorage = computed(() => route.path === '/sealed-storage')
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<template>
|
|
20
|
+
<div class="app-shell">
|
|
21
|
+
<AppHeader class="app-shell__header" variant="dark">
|
|
22
|
+
<template #brand>
|
|
23
|
+
<span class="brand-mark" aria-hidden="true">◆</span>
|
|
24
|
+
<span>Meddleware</span>
|
|
25
|
+
</template>
|
|
26
|
+
<template #actions>
|
|
27
|
+
<StatusWidget />
|
|
28
|
+
<ColorModeControl :model-value="mode" @update:model-value="set" />
|
|
29
|
+
</template>
|
|
30
|
+
</AppHeader>
|
|
31
|
+
|
|
32
|
+
<AppSidebar class="app-shell__sidebar" variant="dark">
|
|
33
|
+
<nav aria-label="Tools">
|
|
34
|
+
<router-link to="/walrus" custom v-slot="{ navigate }">
|
|
35
|
+
<SidebarItem label="Walrus" icon="🗄" :active="isWalrus" @click="navigate" />
|
|
36
|
+
</router-link>
|
|
37
|
+
<router-link to="/access-gate" custom v-slot="{ navigate }">
|
|
38
|
+
<SidebarItem label="Access Gate" icon="🔐" :active="isAccessGate" @click="navigate" />
|
|
39
|
+
</router-link>
|
|
40
|
+
<router-link to="/sealed-storage" custom v-slot="{ navigate }">
|
|
41
|
+
<SidebarItem label="Sealed Storage" icon="🔒" :active="isSealedStorage" @click="navigate" />
|
|
42
|
+
</router-link>
|
|
43
|
+
</nav>
|
|
44
|
+
</AppSidebar>
|
|
45
|
+
|
|
46
|
+
<main class="app-shell__main">
|
|
47
|
+
<RouterView />
|
|
48
|
+
</main>
|
|
49
|
+
|
|
50
|
+
<AppFooter class="app-shell__footer" variant="transparent">
|
|
51
|
+
<span>© {{ year }} Meddleware</span>
|
|
52
|
+
</AppFooter>
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<style scoped>
|
|
57
|
+
.brand-mark {
|
|
58
|
+
color: var(--gold);
|
|
59
|
+
}
|
|
60
|
+
</style>
|
package/src/env.d.ts
ADDED
package/src/main.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createApp } from 'vue'
|
|
2
|
+
import { createPinia } from 'pinia'
|
|
3
|
+
|
|
4
|
+
// Shared design system: tokens first (defines CSS vars), then base element defaults.
|
|
5
|
+
import '@meddleware/design-tokens/tokens.css'
|
|
6
|
+
import '@meddleware/ui/base.css'
|
|
7
|
+
import './styles.css'
|
|
8
|
+
|
|
9
|
+
import { useColorMode } from '@meddleware/ui'
|
|
10
|
+
import App from './App.vue'
|
|
11
|
+
import router from './router'
|
|
12
|
+
|
|
13
|
+
// Default to dark on first load (persisted to localStorage thereafter).
|
|
14
|
+
// Applied before mount to avoid a light-mode flash.
|
|
15
|
+
useColorMode('dark')
|
|
16
|
+
|
|
17
|
+
const app = createApp(App)
|
|
18
|
+
app.use(createPinia())
|
|
19
|
+
app.use(router)
|
|
20
|
+
app.mount('#app')
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createRouter, createWebHistory } from 'vue-router'
|
|
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'
|
|
6
|
+
|
|
7
|
+
const router = createRouter({
|
|
8
|
+
history: createWebHistory(import.meta.env.BASE_URL),
|
|
9
|
+
routes: [
|
|
10
|
+
{ path: '/', component: Home },
|
|
11
|
+
{ path: '/walrus', component: WalrusPage },
|
|
12
|
+
{ path: '/access-gate', component: AccessGatePage },
|
|
13
|
+
{ path: '/sealed-storage', component: SealedStoragePage },
|
|
14
|
+
],
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
export default router
|
package/src/styles.css
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Dashboard app-layout styles. Design tokens + element defaults come from
|
|
3
|
+
* @meddleware/design-tokens + @meddleware/ui/base.css (imported in main.ts).
|
|
4
|
+
* This file holds only the app-shell grid and page-content helpers.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#app {
|
|
8
|
+
min-height: 100vh;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* App shell: full-width header on top; sidebar pinned left immediately under the
|
|
13
|
+
* header down to the bottom of the page/viewport; main fills the central space;
|
|
14
|
+
* footer spans from the sidebar's right edge to the viewport's right edge.
|
|
15
|
+
*/
|
|
16
|
+
.app-shell {
|
|
17
|
+
display: grid;
|
|
18
|
+
grid-template-columns: var(--mw-sidebar-width, 240px) 1fr;
|
|
19
|
+
grid-template-rows: var(--mw-header-height, 56px) 1fr auto;
|
|
20
|
+
grid-template-areas:
|
|
21
|
+
"header header"
|
|
22
|
+
"sidebar main"
|
|
23
|
+
"sidebar footer";
|
|
24
|
+
min-height: 100vh;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.app-shell__header { grid-area: header; }
|
|
28
|
+
.app-shell__sidebar { grid-area: sidebar; }
|
|
29
|
+
.app-shell__main { grid-area: main; min-width: 0; padding: 1.5rem; }
|
|
30
|
+
.app-shell__footer { grid-area: footer; }
|
|
31
|
+
|
|
32
|
+
@media (max-width: 720px) {
|
|
33
|
+
.app-shell {
|
|
34
|
+
grid-template-columns: 1fr;
|
|
35
|
+
grid-template-areas:
|
|
36
|
+
"header"
|
|
37
|
+
"main"
|
|
38
|
+
"footer";
|
|
39
|
+
}
|
|
40
|
+
.app-shell__sidebar { display: none; }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.prose {
|
|
44
|
+
max-width: 68ch;
|
|
45
|
+
color: var(--muted);
|
|
46
|
+
}
|
|
47
|
+
.prose h2 {
|
|
48
|
+
color: var(--text);
|
|
49
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
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>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { UiCard } from '@meddleware/ui'
|
|
3
|
+
import { useRouter } from 'vue-router'
|
|
4
|
+
|
|
5
|
+
const router = useRouter()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<div class="home">
|
|
10
|
+
<h1>Meddleware Tools</h1>
|
|
11
|
+
<p class="prose">
|
|
12
|
+
Decentralised storage and smart-contract-powered access control — hosted and ready to use.
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<div class="card-grid">
|
|
16
|
+
<UiCard class="tool-card" @click="router.push('/walrus')">
|
|
17
|
+
<h2>🗄 Walrus</h2>
|
|
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
|
+
</UiCard>
|
|
29
|
+
|
|
30
|
+
<UiCard class="tool-card" @click="router.push('/access-gate')">
|
|
31
|
+
<h2>🔐 Access Gate</h2>
|
|
32
|
+
<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
|
+
</UiCard>
|
|
43
|
+
|
|
44
|
+
<UiCard class="tool-card" @click="router.push('/sealed-storage')">
|
|
45
|
+
<h2>🔒 Sealed Storage</h2>
|
|
46
|
+
<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
|
+
</UiCard>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<style scoped>
|
|
62
|
+
.home { max-width: 900px; }
|
|
63
|
+
h1 { margin-top: 0; }
|
|
64
|
+
|
|
65
|
+
.card-grid {
|
|
66
|
+
display: grid;
|
|
67
|
+
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
68
|
+
gap: 1rem;
|
|
69
|
+
margin-top: 1.5rem;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.tool-card { cursor: pointer; }
|
|
73
|
+
.tool-card h2 { margin-top: 0; }
|
|
74
|
+
|
|
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
|
+
</style>
|
|
@@ -0,0 +1,99 @@
|
|
|
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>
|
|
@@ -0,0 +1,88 @@
|
|
|
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>
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"verbatimModuleSyntax": true,
|
|
13
|
+
"jsx": "preserve",
|
|
14
|
+
"types": ["node"],
|
|
15
|
+
"noEmit": true
|
|
16
|
+
},
|
|
17
|
+
"include": ["src/**/*.ts", "src/**/*.vue", "src/**/*.d.ts", "vite.config.ts"]
|
|
18
|
+
}
|