@meddleware/walrus-ui 0.1.1 → 0.1.2
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 +6 -5
- package/src/App.vue +108 -92
- package/src/main.ts +1 -0
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meddleware/walrus-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Standalone Vue 3 SPA for uploading blobs to Walrus decentralised storage and managing owned blobs — wallet-connected, NFT-gated relay support.",
|
|
5
|
-
"author": "
|
|
5
|
+
"author": "Meddleware <dev@meddleware.co.uk>",
|
|
6
6
|
"license": "0BSD",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -29,10 +29,11 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@meddleware/design-tokens": "^0.1.
|
|
32
|
+
"@meddleware/design-tokens": "^0.1.2",
|
|
33
33
|
"@meddleware/nft-gate-client": "^0.0.3",
|
|
34
|
-
"@meddleware/
|
|
35
|
-
"@meddleware/walrus-
|
|
34
|
+
"@meddleware/ui": "^0.1.6",
|
|
35
|
+
"@meddleware/walrus-client": "^0.0.3",
|
|
36
|
+
"@meddleware/walrus-relay": "^0.1.1",
|
|
36
37
|
"@mysten/sui": "~2.17.0",
|
|
37
38
|
"@mysten/wallet-standard": "~0.19.9",
|
|
38
39
|
"@mysten/walrus": "~1.1.7",
|
package/src/App.vue
CHANGED
|
@@ -10,11 +10,15 @@ import {
|
|
|
10
10
|
import type { UploadResult } from '@meddleware/walrus-relay'
|
|
11
11
|
// Lightweight URL import — just the wasm asset URL (does not pull the walrus client).
|
|
12
12
|
import walrusWasmUrl from '@mysten/walrus-wasm/web/walrus_wasm_bg.wasm?url'
|
|
13
|
+
import { AppHeader, AppFooter, ColorModeControl, useColorMode } from '@meddleware/ui'
|
|
13
14
|
import { useWallet, getSuiClient } from './wallet.js'
|
|
14
15
|
import { NETWORK, OPERATOR_RELAY_HOSTS, relayHosts, accessGate, uploadRelayMaxTipMist } from './config.js'
|
|
15
16
|
import { runBlobUpload } from './upload-flow.js'
|
|
16
17
|
import MyBlobs from './components/MyBlobs.vue'
|
|
17
18
|
|
|
19
|
+
const isEmbedded = new URLSearchParams(window.location.search).has('embedded')
|
|
20
|
+
const { mode, set } = useColorMode('dark')
|
|
21
|
+
|
|
18
22
|
type Tab = 'upload' | 'blobs'
|
|
19
23
|
const activeTab = ref<Tab>('upload')
|
|
20
24
|
|
|
@@ -85,133 +89,149 @@ function onUploaded(r: UploadResult): void {
|
|
|
85
89
|
</script>
|
|
86
90
|
|
|
87
91
|
<template>
|
|
88
|
-
<div class="
|
|
89
|
-
<
|
|
90
|
-
<
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
<nav class="tabs" aria-label="Feature tabs">
|
|
98
|
-
<button
|
|
99
|
-
type="button"
|
|
100
|
-
class="tab"
|
|
101
|
-
:class="{ active: activeTab === 'upload' }"
|
|
102
|
-
@click="activeTab = 'upload'"
|
|
103
|
-
>
|
|
104
|
-
Upload
|
|
105
|
-
</button>
|
|
106
|
-
<button
|
|
107
|
-
type="button"
|
|
108
|
-
class="tab"
|
|
109
|
-
:class="{ active: activeTab === 'blobs' }"
|
|
110
|
-
@click="activeTab = 'blobs'"
|
|
111
|
-
>
|
|
112
|
-
My Blobs
|
|
113
|
-
</button>
|
|
114
|
-
</nav>
|
|
115
|
-
|
|
116
|
-
<section class="wallet">
|
|
117
|
-
<template v-if="account">
|
|
118
|
-
<span class="addr">{{ account.address.slice(0, 8) }}…{{ account.address.slice(-4) }}</span>
|
|
119
|
-
<button type="button" @click="disconnect">Disconnect</button>
|
|
92
|
+
<div class="app" :class="{ 'app--embedded': isEmbedded }">
|
|
93
|
+
<AppHeader v-if="!isEmbedded" variant="dark">
|
|
94
|
+
<template #brand>
|
|
95
|
+
<span>Walrus Assets</span>
|
|
96
|
+
</template>
|
|
97
|
+
<template #actions>
|
|
98
|
+
<TipConfigBadge :host="OPERATOR_RELAY_HOSTS[NETWORK]" />
|
|
99
|
+
<ColorModeControl :model-value="mode" @update:model-value="set" />
|
|
120
100
|
</template>
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
101
|
+
</AppHeader>
|
|
102
|
+
|
|
103
|
+
<div class="page">
|
|
104
|
+
<p class="sub">Upload and manage blobs on Walrus decentralised storage ({{ NETWORK }}).</p>
|
|
105
|
+
|
|
106
|
+
<nav class="tabs" aria-label="Feature tabs">
|
|
107
|
+
<button
|
|
108
|
+
type="button"
|
|
109
|
+
class="tab"
|
|
110
|
+
:class="{ active: activeTab === 'upload' }"
|
|
111
|
+
@click="activeTab = 'upload'"
|
|
112
|
+
>
|
|
113
|
+
Upload
|
|
124
114
|
</button>
|
|
115
|
+
<button
|
|
116
|
+
type="button"
|
|
117
|
+
class="tab"
|
|
118
|
+
:class="{ active: activeTab === 'blobs' }"
|
|
119
|
+
@click="activeTab = 'blobs'"
|
|
120
|
+
>
|
|
121
|
+
My Blobs
|
|
122
|
+
</button>
|
|
123
|
+
</nav>
|
|
124
|
+
|
|
125
|
+
<section class="wallet">
|
|
126
|
+
<template v-if="account">
|
|
127
|
+
<span class="addr">{{ account.address.slice(0, 8) }}…{{ account.address.slice(-4) }}</span>
|
|
128
|
+
<button type="button" @click="disconnect">Disconnect</button>
|
|
129
|
+
</template>
|
|
130
|
+
<template v-else>
|
|
131
|
+
<button type="button" :disabled="!wallets.length" @click="onConnectFirst">
|
|
132
|
+
{{ wallets.length ? 'Connect wallet' : 'No wallet detected' }}
|
|
133
|
+
</button>
|
|
134
|
+
</template>
|
|
135
|
+
</section>
|
|
136
|
+
|
|
137
|
+
<template v-if="activeTab === 'upload'">
|
|
138
|
+
<AccessGateCta
|
|
139
|
+
:gate-configured="gateState.gateConfigured"
|
|
140
|
+
:has-access="gateState.hasAccess.value"
|
|
141
|
+
:busy="purchasing"
|
|
142
|
+
:price-mist="gate?.priceMist ?? null"
|
|
143
|
+
@purchase="onPurchase"
|
|
144
|
+
/>
|
|
145
|
+
|
|
146
|
+
<WalrusUpload
|
|
147
|
+
:hosts="relayHosts(NETWORK)"
|
|
148
|
+
:connected="!!account"
|
|
149
|
+
:access="{ gateConfigured: gateState.gateConfigured, hasAccess: gateState.hasAccess }"
|
|
150
|
+
:perform-upload="performUpload"
|
|
151
|
+
@uploaded="onUploaded"
|
|
152
|
+
/>
|
|
153
|
+
|
|
154
|
+
<section v-if="result" class="result">
|
|
155
|
+
<h2>Uploaded ✓</h2>
|
|
156
|
+
<p><strong>Blob ID:</strong> <code>{{ result.blobId }}</code></p>
|
|
157
|
+
<p>
|
|
158
|
+
<strong>URL:</strong>
|
|
159
|
+
<a :href="result.url" target="_blank" rel="noopener">{{ result.url }}</a>
|
|
160
|
+
</p>
|
|
161
|
+
<p v-if="result.digest"><strong>Certify tx:</strong> <code>{{ result.digest }}</code></p>
|
|
162
|
+
</section>
|
|
125
163
|
</template>
|
|
126
|
-
</section>
|
|
127
|
-
|
|
128
|
-
<template v-if="activeTab === 'upload'">
|
|
129
|
-
<AccessGateCta
|
|
130
|
-
:gate-configured="gateState.gateConfigured"
|
|
131
|
-
:has-access="gateState.hasAccess.value"
|
|
132
|
-
:busy="purchasing"
|
|
133
|
-
:price-mist="gate?.priceMist ?? null"
|
|
134
|
-
@purchase="onPurchase"
|
|
135
|
-
/>
|
|
136
164
|
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
:
|
|
140
|
-
:
|
|
141
|
-
:perform-upload="performUpload"
|
|
142
|
-
@uploaded="onUploaded"
|
|
165
|
+
<MyBlobs
|
|
166
|
+
v-if="activeTab === 'blobs'"
|
|
167
|
+
:address="account?.address ?? null"
|
|
168
|
+
:build-executor="() => buildExecutor(NETWORK)"
|
|
143
169
|
/>
|
|
170
|
+
</div>
|
|
144
171
|
|
|
145
|
-
|
|
146
|
-
<h2>Uploaded ✓</h2>
|
|
147
|
-
<p><strong>Blob ID:</strong> <code>{{ result.blobId }}</code></p>
|
|
148
|
-
<p>
|
|
149
|
-
<strong>URL:</strong>
|
|
150
|
-
<a :href="result.url" target="_blank" rel="noopener">{{ result.url }}</a>
|
|
151
|
-
</p>
|
|
152
|
-
<p v-if="result.digest"><strong>Certify tx:</strong> <code>{{ result.digest }}</code></p>
|
|
153
|
-
</section>
|
|
154
|
-
</template>
|
|
155
|
-
|
|
156
|
-
<MyBlobs
|
|
157
|
-
v-if="activeTab === 'blobs'"
|
|
158
|
-
:address="account?.address ?? null"
|
|
159
|
-
:build-executor="() => buildExecutor(NETWORK)"
|
|
160
|
-
/>
|
|
161
|
-
|
|
162
|
-
<footer class="foot">
|
|
163
|
-
<p>© MeddleWare · <a href="https://sui.meddleware.co.uk">more SUI tools</a></p>
|
|
164
|
-
</footer>
|
|
172
|
+
<AppFooter v-if="!isEmbedded" />
|
|
165
173
|
</div>
|
|
166
174
|
</template>
|
|
167
175
|
|
|
168
176
|
<style scoped>
|
|
177
|
+
.app {
|
|
178
|
+
min-height: 100vh;
|
|
179
|
+
display: flex;
|
|
180
|
+
flex-direction: column;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.app--embedded {
|
|
184
|
+
min-height: 100%;
|
|
185
|
+
}
|
|
186
|
+
|
|
169
187
|
.page {
|
|
170
188
|
max-width: 640px;
|
|
171
189
|
margin: 0 auto;
|
|
172
190
|
padding: 2rem 1.25rem 4rem;
|
|
191
|
+
flex: 1;
|
|
173
192
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
gap: 1rem;
|
|
179
|
-
flex-wrap: wrap;
|
|
180
|
-
}
|
|
181
|
-
.head h1 {
|
|
182
|
-
margin: 0;
|
|
183
|
-
font-size: 1.8rem;
|
|
193
|
+
|
|
194
|
+
.app--embedded .page {
|
|
195
|
+
padding-top: 1rem;
|
|
196
|
+
padding-bottom: 1rem;
|
|
184
197
|
}
|
|
198
|
+
|
|
185
199
|
.sub {
|
|
186
|
-
color: var(--
|
|
200
|
+
color: var(--muted);
|
|
187
201
|
margin: 0.25rem 0 0;
|
|
188
202
|
}
|
|
203
|
+
|
|
189
204
|
.wallet {
|
|
190
205
|
display: flex;
|
|
191
206
|
align-items: center;
|
|
192
207
|
gap: 0.75rem;
|
|
193
208
|
margin: 1.25rem 0;
|
|
194
209
|
}
|
|
210
|
+
|
|
195
211
|
.addr {
|
|
196
212
|
font-family: monospace;
|
|
197
213
|
font-size: 0.9rem;
|
|
198
214
|
}
|
|
215
|
+
|
|
199
216
|
.result {
|
|
200
217
|
margin-top: 1.5rem;
|
|
201
218
|
padding: 1rem;
|
|
202
|
-
border: 1px solid var(--
|
|
219
|
+
border: 1px solid var(--border);
|
|
203
220
|
border-radius: 10px;
|
|
204
221
|
word-break: break-all;
|
|
205
222
|
}
|
|
223
|
+
|
|
206
224
|
.result code {
|
|
207
225
|
font-size: 0.85rem;
|
|
208
226
|
}
|
|
227
|
+
|
|
209
228
|
.tabs {
|
|
210
229
|
display: flex;
|
|
211
230
|
gap: 0.25rem;
|
|
212
231
|
margin: 1rem 0 0.5rem;
|
|
213
|
-
border-bottom: 2px solid var(--
|
|
232
|
+
border-bottom: 2px solid var(--border);
|
|
214
233
|
}
|
|
234
|
+
|
|
215
235
|
.tab {
|
|
216
236
|
background: none;
|
|
217
237
|
border: none;
|
|
@@ -220,16 +240,12 @@ function onUploaded(r: UploadResult): void {
|
|
|
220
240
|
margin-bottom: -2px;
|
|
221
241
|
cursor: pointer;
|
|
222
242
|
font-size: 0.95rem;
|
|
223
|
-
color: var(--
|
|
243
|
+
color: var(--muted);
|
|
224
244
|
}
|
|
245
|
+
|
|
225
246
|
.tab.active {
|
|
226
|
-
border-bottom-color: var(--
|
|
227
|
-
color: var(--
|
|
247
|
+
border-bottom-color: var(--accent);
|
|
248
|
+
color: var(--text);
|
|
228
249
|
font-weight: 600;
|
|
229
250
|
}
|
|
230
|
-
.foot {
|
|
231
|
-
margin-top: 3rem;
|
|
232
|
-
font-size: 0.85rem;
|
|
233
|
-
color: var(--mw-color-text-muted, #666);
|
|
234
|
-
}
|
|
235
251
|
</style>
|