@meddleware/seal-ui 0.0.19 → 0.0.21
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 +31 -9
- package/src/App.vue +14 -1
- package/src/components/SealView.vue +88 -69
- package/src/config.ts +2 -2
- package/src/styles.css +1 -1
- package/vite.config.ts +5 -0
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meddleware/seal-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"homepage": "https://docs.meddleware.co.uk/blockchain/sui/sealed-storage/",
|
|
5
5
|
"description": "Standalone Vue 3 SPA for Sealed Storage — client-side Seal encryption + access-gated, decentralised Walrus storage on Sui.",
|
|
6
|
-
"author": "MeddleWare <meddleware
|
|
6
|
+
"author": "MeddleWare <dev@meddleware.co.uk>",
|
|
7
7
|
"license": "0BSD",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -34,31 +34,53 @@
|
|
|
34
34
|
"preview": "vite preview",
|
|
35
35
|
"type-check": "vue-tsc --noEmit",
|
|
36
36
|
"test": "vitest run",
|
|
37
|
-
"test:watch": "vitest"
|
|
37
|
+
"test:watch": "vitest",
|
|
38
|
+
"lint:css": "stylelint \"src/**/*.{css,vue}\"",
|
|
39
|
+
"lint:js": "eslint .",
|
|
40
|
+
"lint": "npm run lint:css && npm run lint:js && npm run lint:html",
|
|
41
|
+
"lint:html": "html-validate \"src/**/*.vue\""
|
|
38
42
|
},
|
|
39
43
|
"publishConfig": {
|
|
40
44
|
"access": "public"
|
|
41
45
|
},
|
|
42
46
|
"dependencies": {
|
|
43
|
-
"@meddleware/design-tokens": "^0.1.
|
|
44
|
-
"@meddleware/seal-client": "^0.0.
|
|
45
|
-
"@meddleware/ui": "^0.1.
|
|
46
|
-
"@meddleware/wallet-adapter": "^0.0.
|
|
47
|
-
"@mysten/sui": "^2.
|
|
47
|
+
"@meddleware/design-tokens": "^0.1.7",
|
|
48
|
+
"@meddleware/seal-client": "^0.0.8",
|
|
49
|
+
"@meddleware/ui": "^0.1.28",
|
|
50
|
+
"@meddleware/wallet-adapter": "^0.0.10",
|
|
51
|
+
"@mysten/sui": "^2.33.1",
|
|
48
52
|
"@mysten/wallet-standard": "^0.21.0",
|
|
49
53
|
"vue": "^3.5.43"
|
|
50
54
|
},
|
|
51
55
|
"devDependencies": {
|
|
52
56
|
"@types/node": "~24.12.2",
|
|
53
57
|
"@vitejs/plugin-vue": "^6.0.9",
|
|
58
|
+
"@vue/eslint-config-typescript": "^14.9.0",
|
|
54
59
|
"@vue/test-utils": "^2.5.1",
|
|
60
|
+
"autoprefixer": "^10.4.20",
|
|
61
|
+
"eslint": "^10.11.0",
|
|
62
|
+
"eslint-plugin-vue": "^10.11.1",
|
|
63
|
+
"eslint-plugin-vuejs-accessibility": "^2.6.0",
|
|
64
|
+
"html-validate": "^11.16.1",
|
|
65
|
+
"html-validate-vue": "^9.3.1",
|
|
66
|
+
"jiti": "^2.7.0",
|
|
55
67
|
"jsdom": "^30.1.0",
|
|
68
|
+
"postcss": "^8.4.49",
|
|
69
|
+
"postcss-html": "^2.0.0",
|
|
70
|
+
"stylelint": "^17.15.0",
|
|
71
|
+
"stylelint-config-standard": "^40.0.0",
|
|
56
72
|
"typescript": "~6.0.0",
|
|
57
73
|
"vite": "^8.3.0",
|
|
58
74
|
"vitest": "~5.0.1",
|
|
75
|
+
"vue-eslint-parser": "^10.4.1",
|
|
59
76
|
"vue-tsc": "~3.3.11"
|
|
60
77
|
},
|
|
61
78
|
"engines": {
|
|
62
79
|
"node": "^22.18.0 || >=24.12.0"
|
|
63
|
-
}
|
|
80
|
+
},
|
|
81
|
+
"browserslist": [
|
|
82
|
+
"> 0.5%",
|
|
83
|
+
"last 2 versions",
|
|
84
|
+
"not dead"
|
|
85
|
+
]
|
|
64
86
|
}
|
package/src/App.vue
CHANGED
|
@@ -22,7 +22,9 @@ const DEV_URL = import.meta.env.VITE_DEV_URL || 'https://dev.meddleware.co.uk/
|
|
|
22
22
|
</template>
|
|
23
23
|
</AppHeader>
|
|
24
24
|
|
|
25
|
-
<
|
|
25
|
+
<div class="app__content">
|
|
26
|
+
<SealView />
|
|
27
|
+
</div>
|
|
26
28
|
|
|
27
29
|
<AppFooter :docs-url="DOCS_URL" :dev-url="DEV_URL" />
|
|
28
30
|
</div>
|
|
@@ -35,6 +37,17 @@ const DEV_URL = import.meta.env.VITE_DEV_URL || 'https://dev.meddleware.co.uk/
|
|
|
35
37
|
flex-direction: column;
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
/* Centre the tool at the shared tool-content width when running standalone. The dashboard
|
|
41
|
+
supplies its own width container, so this lives in the shell, not SealView. */
|
|
42
|
+
.app__content {
|
|
43
|
+
flex: 1;
|
|
44
|
+
width: 100%;
|
|
45
|
+
max-width: var(--mw-tool-content-max);
|
|
46
|
+
margin: 0 auto;
|
|
47
|
+
box-sizing: border-box;
|
|
48
|
+
padding: 1.5rem 1.25rem 4rem;
|
|
49
|
+
}
|
|
50
|
+
|
|
38
51
|
.badge {
|
|
39
52
|
font-size: 0.75rem;
|
|
40
53
|
padding: 0.2rem 0.5rem;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// global stylesheet (which restyles body / #app / bare inputs). The standalone app keeps those
|
|
9
9
|
// globals via main.ts → styles.css.
|
|
10
10
|
import { computed, onMounted, ref, watch } from 'vue'
|
|
11
|
-
import { AppTabNav, UiStepper, type AppTab, type StepperStep } from '@meddleware/ui'
|
|
11
|
+
import { AppTabNav, UiStepper, UiTabPanel, UiToolIntro, type AppTab, type StepperStep } from '@meddleware/ui'
|
|
12
12
|
import { Transaction } from '@mysten/sui/transactions'
|
|
13
13
|
import {
|
|
14
14
|
buildPublishSealedContentTx,
|
|
@@ -111,6 +111,13 @@ async function fetchGateSuggestions(provider: SealPolicyProvider | null): Promis
|
|
|
111
111
|
const encType = ref(providers[0]?.type ?? '')
|
|
112
112
|
const encProvider = computed(() => providers.find((p) => p.type === encType.value) ?? null)
|
|
113
113
|
const encValues = ref<Record<string, string | boolean>>({})
|
|
114
|
+
|
|
115
|
+
/** One input per policy field; its type follows the field kind (v-model handles each type). */
|
|
116
|
+
function fieldInputType(kind: string): string {
|
|
117
|
+
if (kind === 'datetime') return 'datetime-local'
|
|
118
|
+
if (kind === 'boolean') return 'checkbox'
|
|
119
|
+
return 'text'
|
|
120
|
+
}
|
|
114
121
|
const encFile = ref<File | null>(null)
|
|
115
122
|
const encLabel = ref('')
|
|
116
123
|
const manifest = ref<SealedManifest | null>(null)
|
|
@@ -352,10 +359,10 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
352
359
|
</script>
|
|
353
360
|
|
|
354
361
|
<template>
|
|
355
|
-
<div class="page">
|
|
356
|
-
<p class="muted">Client-side encrypted, access-gated storage on Walrus + Sui.</p>
|
|
357
362
|
|
|
358
|
-
<
|
|
363
|
+
<UiToolIntro>Client-side encrypted, access-gated storage on Walrus + Sui.</UiToolIntro>
|
|
364
|
+
|
|
365
|
+
<p v-if="!SEAL_CONFIGURED" class="notice notice--warn">
|
|
359
366
|
<template v-if="NETWORK === 'mainnet'">
|
|
360
367
|
Seal is not configured for mainnet. Set
|
|
361
368
|
<code>VITE_SEAL_PACKAGE_ID_MAINNET</code>,
|
|
@@ -366,15 +373,15 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
366
373
|
This deployment has no Seal policy package or key-server committee configured
|
|
367
374
|
(<code>VITE_SEAL_PACKAGE_ID_*</code> / <code>VITE_SEAL_SERVER_OBJECT_IDS_*</code>).
|
|
368
375
|
</template>
|
|
369
|
-
</
|
|
376
|
+
</p>
|
|
370
377
|
|
|
371
378
|
<WalletGuard message="Connect a Sui wallet to encrypt and decrypt sealed content.">
|
|
372
|
-
<AppTabNav :tabs="TABS"
|
|
379
|
+
<AppTabNav v-model="tab" :tabs="TABS" id-prefix="seal" aria-label="Sealed storage" class="seal-tabs" />
|
|
373
380
|
|
|
374
|
-
<
|
|
381
|
+
<p v-if="errorMsg" class="notice notice--error" role="alert">{{ errorMsg }}</p>
|
|
375
382
|
|
|
376
383
|
<!-- Encrypt -->
|
|
377
|
-
<
|
|
384
|
+
<UiTabPanel v-show="tab === 'encrypt'" id-prefix="seal" tab="encrypt" class="card">
|
|
378
385
|
<UiStepper :steps="ENC_STEPS" v-model="encStep" />
|
|
379
386
|
|
|
380
387
|
<!-- Step 0: Policy -->
|
|
@@ -398,27 +405,33 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
398
405
|
<template v-if="encProvider">
|
|
399
406
|
<template v-for="f in encProvider.describe().encryptFields" :key="f.name">
|
|
400
407
|
<!-- Gate ID field: show a picker when wallet-owned gates are available -->
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
<
|
|
404
|
-
|
|
408
|
+
<!-- The picker/manual toggle is a sibling of the label: a label may only contain its own control. -->
|
|
409
|
+
<template v-if="f.name === 'gateId'">
|
|
410
|
+
<label v-if="!encGateLoading && encGateSuggestions.length && !encGateManual" class="field">
|
|
411
|
+
<span>{{ f.label }}<template v-if="f.required"> *</template></span>
|
|
405
412
|
<select v-model="encValues[f.name]">
|
|
406
413
|
<option value="">Select a gate…</option>
|
|
407
414
|
<option v-for="s in encGateSuggestions" :key="s.value" :value="s.value">{{ s.label }}</option>
|
|
408
415
|
</select>
|
|
409
|
-
|
|
416
|
+
</label>
|
|
417
|
+
<label v-else class="field">
|
|
418
|
+
<span>{{ f.label }}<template v-if="f.required"> *</template></span>
|
|
419
|
+
<span v-if="encGateLoading" class="muted muted--sm">Loading your gates…</span>
|
|
420
|
+
<input v-else v-model="encValues[f.name]" type="text" :placeholder="f.help" />
|
|
421
|
+
</label>
|
|
422
|
+
<template v-if="!encGateLoading && encGateSuggestions.length">
|
|
423
|
+
<button v-if="!encGateManual" type="button" class="link link--spaced" @click="encGateManual = true; encValues[f.name] = ''">Enter ID manually</button>
|
|
424
|
+
<button v-else type="button" class="link link--spaced" @click="encGateManual = false; encValues[f.name] = ''">← Back to picker</button>
|
|
410
425
|
</template>
|
|
411
|
-
|
|
412
|
-
<input type="text" v-model="encValues[f.name]" :placeholder="f.help" />
|
|
413
|
-
<button v-if="encGateSuggestions.length" class="link" style="margin-top:0.25rem" @click="encGateManual = false; encValues[f.name] = ''">← Back to picker</button>
|
|
414
|
-
</template>
|
|
415
|
-
</label>
|
|
426
|
+
</template>
|
|
416
427
|
<!-- All other fields: generic rendering -->
|
|
417
428
|
<label v-else class="field" :class="{ checkbox: f.kind === 'boolean' }">
|
|
418
429
|
<span>{{ f.label }}<template v-if="f.required"> *</template></span>
|
|
419
|
-
<input
|
|
420
|
-
|
|
421
|
-
|
|
430
|
+
<input
|
|
431
|
+
v-model="encValues[f.name]"
|
|
432
|
+
:type="fieldInputType(f.kind)"
|
|
433
|
+
:placeholder="fieldInputType(f.kind) === 'text' ? f.help : undefined"
|
|
434
|
+
/>
|
|
422
435
|
</label>
|
|
423
436
|
</template>
|
|
424
437
|
</template>
|
|
@@ -447,36 +460,38 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
447
460
|
<p v-if="encLabel" class="muted">Label: <strong>{{ encLabel }}</strong></p>
|
|
448
461
|
</div>
|
|
449
462
|
|
|
450
|
-
<button v-if="!manifest" class="primary" :disabled="busy || disabled" @click="performEncrypt">
|
|
463
|
+
<button type="button" v-if="!manifest" class="primary" :disabled="busy || disabled" @click="performEncrypt">
|
|
451
464
|
{{ busy ? 'Working…' : 'Encrypt & store' }}
|
|
452
465
|
</button>
|
|
453
466
|
|
|
454
|
-
<
|
|
455
|
-
<
|
|
456
|
-
|
|
457
|
-
|
|
467
|
+
<template v-if="manifest">
|
|
468
|
+
<figure class="enc-result">
|
|
469
|
+
<figcaption class="muted">Manifest — save this; it's required to decrypt (it holds no secrets):</figcaption>
|
|
470
|
+
<pre class="manifest">{{ JSON.stringify(manifest, null, 2) }}</pre>
|
|
471
|
+
</figure>
|
|
472
|
+
<button type="button" class="link" @click="downloadManifest">Download manifest</button>
|
|
458
473
|
|
|
459
|
-
<
|
|
474
|
+
<section v-if="manifest.policyType === 'nft-gate'" class="enc-publish">
|
|
460
475
|
<p class="muted">
|
|
461
476
|
Optional: publish an on-chain pointer so this gate's pass-holders can discover and unlock
|
|
462
477
|
this content in the Unlock tab (no need to share the manifest).
|
|
463
478
|
</p>
|
|
464
|
-
<button class="primary" :disabled="busy || !account" @click="performPublish">
|
|
479
|
+
<button type="button" class="primary" :disabled="busy || !account" @click="performPublish">
|
|
465
480
|
{{ busy ? 'Working…' : 'Publish discovery pointer' }}
|
|
466
481
|
</button>
|
|
467
482
|
<span v-if="!account" class="muted"> — connect a wallet first.</span>
|
|
468
483
|
<p v-if="publishDigest" class="muted">Published in tx {{ publishDigest.slice(0, 10) }}…</p>
|
|
469
|
-
</
|
|
470
|
-
</
|
|
484
|
+
</section>
|
|
485
|
+
</template>
|
|
471
486
|
|
|
472
487
|
<div v-if="!manifest" class="nav-row">
|
|
473
488
|
<button type="button" class="link" @click="encStep--">Back</button>
|
|
474
489
|
</div>
|
|
475
490
|
</template>
|
|
476
|
-
</
|
|
491
|
+
</UiTabPanel>
|
|
477
492
|
|
|
478
493
|
<!-- Unlock -->
|
|
479
|
-
<
|
|
494
|
+
<UiTabPanel v-show="tab === 'unlock'" id-prefix="seal" tab="unlock" class="card">
|
|
480
495
|
<UiStepper :steps="UNLOCK_STEPS" v-model="unlockStep" />
|
|
481
496
|
|
|
482
497
|
<!-- Step 0: Gate selector -->
|
|
@@ -484,22 +499,23 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
484
499
|
<p class="muted">
|
|
485
500
|
Discover content sealed to an access gate and decrypt it with a pass you hold.
|
|
486
501
|
</p>
|
|
487
|
-
<label class="field">
|
|
502
|
+
<label v-if="!unlockGateLoading && unlockGateSuggestions.length && !unlockGateManual" class="field">
|
|
488
503
|
<span>Access gate ID</span>
|
|
489
|
-
<
|
|
490
|
-
|
|
491
|
-
<
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
<
|
|
498
|
-
<input type="text" v-model="unlockGateId" placeholder="0x… gate object id" />
|
|
499
|
-
<button v-if="unlockGateSuggestions.length" class="link" style="margin-top:0.25rem" @click="unlockGateManual = false; unlockGateId = ''">← Back to picker</button>
|
|
500
|
-
</template>
|
|
504
|
+
<select v-model="unlockGateId">
|
|
505
|
+
<option value="">Select a gate…</option>
|
|
506
|
+
<option v-for="s in unlockGateSuggestions" :key="s.value" :value="s.value">{{ s.label }}</option>
|
|
507
|
+
</select>
|
|
508
|
+
</label>
|
|
509
|
+
<label v-else class="field">
|
|
510
|
+
<span>Access gate ID</span>
|
|
511
|
+
<span v-if="unlockGateLoading" class="muted muted--sm">Loading your gates…</span>
|
|
512
|
+
<input v-else v-model="unlockGateId" type="text" placeholder="0x… gate object id" />
|
|
501
513
|
</label>
|
|
502
|
-
<
|
|
514
|
+
<template v-if="!unlockGateLoading && unlockGateSuggestions.length">
|
|
515
|
+
<button v-if="!unlockGateManual" type="button" class="link link--spaced" @click="unlockGateManual = true; unlockGateId = ''">Enter ID manually</button>
|
|
516
|
+
<button v-else type="button" class="link link--spaced" @click="unlockGateManual = false; unlockGateId = ''">← Back to picker</button>
|
|
517
|
+
</template>
|
|
518
|
+
<button type="button" class="primary" :disabled="busy || !unlockGateId" @click="performDiscover">
|
|
503
519
|
{{ busy ? 'Working…' : 'Find sealed content' }}
|
|
504
520
|
</button>
|
|
505
521
|
</template>
|
|
@@ -518,24 +534,24 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
518
534
|
<span>Pass is soulbound</span>
|
|
519
535
|
</label>
|
|
520
536
|
|
|
521
|
-
<
|
|
522
|
-
<
|
|
523
|
-
<p class="muted
|
|
524
|
-
<button class="primary" :disabled="busy || !account || !unlockNftId" @click="performUnlock(item)">
|
|
537
|
+
<article v-for="item in discovered" :key="item.contentId" class="card discovered">
|
|
538
|
+
<h3 class="discovered__title">{{ item.label || '(untitled)' }}</h3>
|
|
539
|
+
<p class="muted discovered__blob">blob {{ item.blobId }}</p>
|
|
540
|
+
<button type="button" class="primary" :disabled="busy || !account || !unlockNftId" @click="performUnlock(item)">
|
|
525
541
|
Unlock & download
|
|
526
542
|
</button>
|
|
527
543
|
<span v-if="!account" class="muted"> — connect a wallet to decrypt.</span>
|
|
528
|
-
</
|
|
544
|
+
</article>
|
|
529
545
|
</div>
|
|
530
546
|
|
|
531
547
|
<div class="nav-row">
|
|
532
548
|
<button type="button" class="link" @click="unlockStep--; discovered = []">Back</button>
|
|
533
549
|
</div>
|
|
534
550
|
</template>
|
|
535
|
-
</
|
|
551
|
+
</UiTabPanel>
|
|
536
552
|
|
|
537
553
|
<!-- Decrypt -->
|
|
538
|
-
<
|
|
554
|
+
<UiTabPanel v-show="tab === 'decrypt'" id-prefix="seal" tab="decrypt" class="card">
|
|
539
555
|
<UiStepper :steps="DEC_STEPS" v-model="decStep" />
|
|
540
556
|
|
|
541
557
|
<!-- Step 0: Manifest input -->
|
|
@@ -544,7 +560,10 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
544
560
|
<span>Manifest (paste JSON or upload)</span>
|
|
545
561
|
<textarea v-model="decManifestText" placeholder='{ "policyType": "...", "id": "...", "blobId": "..." }'></textarea>
|
|
546
562
|
</label>
|
|
547
|
-
<
|
|
563
|
+
<label class="field">
|
|
564
|
+
<span>Or upload a manifest file</span>
|
|
565
|
+
<input type="file" accept="application/json,.json" @change="onManifestFile" />
|
|
566
|
+
</label>
|
|
548
567
|
<p v-if="decManifestError" class="muted">{{ decManifestError }}</p>
|
|
549
568
|
<p v-else-if="decManifestText.trim() && !decManifest" class="muted">Unrecognised or invalid manifest.</p>
|
|
550
569
|
<div class="nav-row">
|
|
@@ -555,7 +574,7 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
555
574
|
<!-- Step 1: Policy fields + decrypt -->
|
|
556
575
|
<template v-else-if="decStep === 1">
|
|
557
576
|
<template v-if="decProvider">
|
|
558
|
-
<p class="muted
|
|
577
|
+
<p class="muted muted--spaced">
|
|
559
578
|
Policy: {{ decProvider.describe().label }} — {{ decProvider.describe().help }}
|
|
560
579
|
</p>
|
|
561
580
|
<label
|
|
@@ -565,25 +584,23 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
565
584
|
:class="{ checkbox: f.kind === 'boolean' }"
|
|
566
585
|
>
|
|
567
586
|
<span>{{ f.label }}<template v-if="f.required"> *</template></span>
|
|
568
|
-
<input v-if="f.kind === 'datetime'" type="datetime-local" v-model="decValues[f.name]" />
|
|
569
|
-
<input v-else-if="f.kind === 'boolean'" type="checkbox" v-model="decValues[f.name]" />
|
|
570
587
|
<input
|
|
571
|
-
v-else
|
|
572
|
-
type="text"
|
|
573
588
|
v-model="decValues[f.name]"
|
|
574
|
-
:
|
|
589
|
+
:type="fieldInputType(f.kind)"
|
|
590
|
+
:placeholder="fieldInputType(f.kind) !== 'text' ? undefined
|
|
591
|
+
: decManifest?.params?.[f.name] != null ? String(decManifest.params[f.name]) : f.help"
|
|
575
592
|
/>
|
|
576
593
|
</label>
|
|
577
594
|
</template>
|
|
578
595
|
|
|
579
596
|
<div class="nav-row">
|
|
580
597
|
<button type="button" class="link" @click="decStep--">Back</button>
|
|
581
|
-
<button class="primary" :disabled="busy || !decProvider" @click="performDecrypt">
|
|
598
|
+
<button type="button" class="primary" :disabled="busy || !decProvider" @click="performDecrypt">
|
|
582
599
|
{{ busy ? 'Working…' : 'Decrypt' }}
|
|
583
600
|
</button>
|
|
584
601
|
</div>
|
|
585
602
|
</template>
|
|
586
|
-
</
|
|
603
|
+
</UiTabPanel>
|
|
587
604
|
|
|
588
605
|
<p v-if="status" class="status muted">{{ status }}</p>
|
|
589
606
|
|
|
@@ -592,16 +609,9 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
592
609
|
servers are unreachable, decryption pauses — storage and retrieval are unaffected.
|
|
593
610
|
</p>
|
|
594
611
|
</WalletGuard>
|
|
595
|
-
</div>
|
|
596
612
|
</template>
|
|
597
613
|
|
|
598
614
|
<style scoped>
|
|
599
|
-
.page {
|
|
600
|
-
max-width: 780px;
|
|
601
|
-
margin: 0 auto;
|
|
602
|
-
flex: 1;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
615
|
.notice {
|
|
606
616
|
border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
|
|
607
617
|
border-radius: 10px;
|
|
@@ -694,6 +704,15 @@ pre.manifest {
|
|
|
694
704
|
}
|
|
695
705
|
|
|
696
706
|
.muted { color: var(--muted, #a89b96); font-size: 0.85rem; }
|
|
707
|
+
.muted--sm { font-size: 0.8rem; }
|
|
708
|
+
.muted--spaced { margin-top: 0.75rem; }
|
|
709
|
+
.link--spaced { margin-top: 0.25rem; }
|
|
710
|
+
.seal-tabs { margin: 1rem 0; }
|
|
711
|
+
.enc-result { margin: 1rem 0 0; }
|
|
712
|
+
.enc-publish { margin-top: 0.75rem; }
|
|
713
|
+
.discovered { margin: 0.5rem 0; }
|
|
714
|
+
.discovered__title { margin: 0; font-size: 1rem; }
|
|
715
|
+
.discovered__blob { word-break: break-all; }
|
|
697
716
|
.status { font-size: 0.85rem; margin-top: 0.5rem; }
|
|
698
717
|
.disclaimer { margin-top: 2rem; }
|
|
699
718
|
</style>
|
package/src/config.ts
CHANGED
|
@@ -27,7 +27,7 @@ export const SEAL_PACKAGE_ID: string =
|
|
|
27
27
|
netEnv('VITE_SEAL_PACKAGE_ID') ||
|
|
28
28
|
// Meddleware's canonical testnet deployment — override with VITE_SEAL_PACKAGE_ID_TESTNET
|
|
29
29
|
(NETWORK === 'testnet'
|
|
30
|
-
? '
|
|
30
|
+
? '0x42cc181f851ef702c1fddc9b925553f03b71784edff49d80fbc260055f86d612'
|
|
31
31
|
: '')
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -102,7 +102,7 @@ export const WALRUS_EPOCHS = Number(env.VITE_WALRUS_EPOCHS || '5')
|
|
|
102
102
|
* Kept in sync with access-gate-ui/src/constants.ts (same deployment).
|
|
103
103
|
*/
|
|
104
104
|
export const ACCESS_GATE_PACKAGE_ID: Record<Network, string> = {
|
|
105
|
-
testnet: '
|
|
105
|
+
testnet: '0x1a81ca177db039585e575beeeee4759466e55910e936a6733e38dbb65025eea4',
|
|
106
106
|
mainnet: '',
|
|
107
107
|
}
|
|
108
108
|
|
package/src/styles.css
CHANGED
package/vite.config.ts
CHANGED
|
@@ -5,4 +5,9 @@ import vue from '@vitejs/plugin-vue'
|
|
|
5
5
|
// (plain fetch), so no @mysten/walrus wasm to exclude here.
|
|
6
6
|
export default defineConfig({
|
|
7
7
|
plugins: [vue()],
|
|
8
|
+
optimizeDeps: {
|
|
9
|
+
// @meddleware/wallet-adapter ships TS + .vue source and holds the shared wallet singleton; if it
|
|
10
|
+
// were pre-bundled, its .vue files (served raw) would load a second copy of the singleton in dev.
|
|
11
|
+
exclude: ['@meddleware/wallet-adapter'],
|
|
12
|
+
},
|
|
8
13
|
})
|