@meddleware/seal-ui 0.0.8 → 0.0.10
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 +2 -2
- package/src/components/SealView.vue +21 -35
- package/src/config.ts +40 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meddleware/seal-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "Standalone Vue 3 SPA for Sealed Storage — client-side Seal encryption + access-gated, decentralised Walrus storage on Sui.",
|
|
5
5
|
"author": "MeddleWare <meddleware@proton.me>",
|
|
6
6
|
"license": "0BSD",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@meddleware/design-tokens": "^0.1.2",
|
|
41
41
|
"@meddleware/seal-client": "^0.0.2",
|
|
42
|
-
"@meddleware/ui": "^0.1.
|
|
42
|
+
"@meddleware/ui": "^0.1.11",
|
|
43
43
|
"@meddleware/wallet-adapter": "^0.0.5",
|
|
44
44
|
"@mysten/seal": "^1.4.7",
|
|
45
45
|
"@mysten/sui": "^2.30.0",
|
|
@@ -8,6 +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 } from 'vue'
|
|
11
|
+
import { AppTabNav, type AppTab } from '@meddleware/ui'
|
|
11
12
|
import { Transaction } from '@mysten/sui/transactions'
|
|
12
13
|
import {
|
|
13
14
|
buildPublishSealedContentTx,
|
|
@@ -20,15 +21,19 @@ import { useWallet } from '../wallet.js'
|
|
|
20
21
|
import { registry, getSealController } from '../seal.js'
|
|
21
22
|
import { storeBlob, readBlob } from '../walrus.js'
|
|
22
23
|
import { discoverSealedContent } from '../sealed-content.js'
|
|
23
|
-
import { NETWORK,
|
|
24
|
+
import { NETWORK, SEAL_CONFIGURED, SEAL_PACKAGE_ID } from '../config.js'
|
|
24
25
|
|
|
25
26
|
const { account, signPersonalMessage, signAndExecute } = useWallet()
|
|
26
27
|
|
|
27
28
|
const providers = registry.list() as SealPolicyProvider[]
|
|
28
|
-
const disabled = computed(() =>
|
|
29
|
+
const disabled = computed(() => !SEAL_CONFIGURED)
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
const TABS: AppTab[] = [
|
|
32
|
+
{ id: 'encrypt', label: 'Encrypt' },
|
|
33
|
+
{ id: 'decrypt', label: 'Decrypt' },
|
|
34
|
+
{ id: 'unlock', label: 'Unlock' },
|
|
35
|
+
]
|
|
36
|
+
const tab = ref<string>('encrypt')
|
|
32
37
|
|
|
33
38
|
// Deep-link from access-gate-ui: ?gate=<id> preselects the nft-gate policy + gate.
|
|
34
39
|
onMounted(() => {
|
|
@@ -272,21 +277,21 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
272
277
|
<div class="page">
|
|
273
278
|
<p class="muted">Client-side encrypted, access-gated storage on Walrus + Sui.</p>
|
|
274
279
|
|
|
275
|
-
<div v-if="
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
280
|
+
<div v-if="!SEAL_CONFIGURED" class="notice notice--warn">
|
|
281
|
+
<template v-if="NETWORK === 'mainnet'">
|
|
282
|
+
Seal is not configured for mainnet. Set
|
|
283
|
+
<code>VITE_SEAL_PACKAGE_ID_MAINNET</code>,
|
|
284
|
+
<code>VITE_SEAL_SERVER_OBJECT_IDS_MAINNET</code>, and
|
|
285
|
+
<code>VITE_SEAL_AGGREGATOR_URLS_MAINNET</code>, then redeploy.
|
|
286
|
+
</template>
|
|
287
|
+
<template v-else>
|
|
288
|
+
This deployment has no Seal policy package or key-server committee configured
|
|
289
|
+
(<code>VITE_SEAL_PACKAGE_ID_*</code> / <code>VITE_SEAL_SERVER_OBJECT_IDS_*</code>).
|
|
290
|
+
</template>
|
|
282
291
|
</div>
|
|
283
292
|
|
|
284
293
|
<WalletGuard message="Connect a Sui wallet to encrypt and decrypt sealed content.">
|
|
285
|
-
<
|
|
286
|
-
<button :class="{ active: tab === 'encrypt' }" @click="tab = 'encrypt'">Encrypt</button>
|
|
287
|
-
<button :class="{ active: tab === 'decrypt' }" @click="tab = 'decrypt'">Decrypt</button>
|
|
288
|
-
<button :class="{ active: tab === 'unlock' }" @click="tab = 'unlock'">Unlock</button>
|
|
289
|
-
</nav>
|
|
294
|
+
<AppTabNav :tabs="TABS" v-model="tab" style="margin: 1rem 0" />
|
|
290
295
|
|
|
291
296
|
<div v-if="errorMsg" class="notice notice--error">{{ errorMsg }}</div>
|
|
292
297
|
|
|
@@ -446,25 +451,6 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
446
451
|
.notice--warn { background: color-mix(in srgb, #d29922 15%, transparent); }
|
|
447
452
|
.notice--error { background: color-mix(in srgb, #f85149 18%, transparent); }
|
|
448
453
|
|
|
449
|
-
.tabs {
|
|
450
|
-
display: flex;
|
|
451
|
-
gap: 0.25rem;
|
|
452
|
-
margin: 1rem 0;
|
|
453
|
-
border-bottom: 1px solid color-mix(in srgb, currentColor 15%, transparent);
|
|
454
|
-
}
|
|
455
|
-
.tabs button {
|
|
456
|
-
background: transparent;
|
|
457
|
-
border: 0;
|
|
458
|
-
color: inherit;
|
|
459
|
-
padding: 0.5rem 0.9rem;
|
|
460
|
-
cursor: pointer;
|
|
461
|
-
opacity: 0.7;
|
|
462
|
-
border-bottom: 2px solid transparent;
|
|
463
|
-
}
|
|
464
|
-
.tabs button.active {
|
|
465
|
-
opacity: 1;
|
|
466
|
-
border-bottom-color: var(--accent, #c0503f);
|
|
467
|
-
}
|
|
468
454
|
|
|
469
455
|
.card {
|
|
470
456
|
background: var(--surface, #1e1917);
|
package/src/config.ts
CHANGED
|
@@ -30,32 +30,53 @@ export const SEAL_PACKAGE_ID: string =
|
|
|
30
30
|
? '0x9f0563bfe42fbd29932cd280cc47efe17f5339b4dc569eb110114665eecc231e'
|
|
31
31
|
: '')
|
|
32
32
|
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Threshold `t` in the t-of-n committee.
|
|
35
|
+
* Testnet default: 2 (matches the 3-server testnet committee)
|
|
36
|
+
* Mainnet default: 5 (matches the 5-of-8 Mysten Labs mainnet committee)
|
|
37
|
+
*/
|
|
38
|
+
export const SEAL_THRESHOLD = Number(
|
|
39
|
+
env.VITE_SEAL_THRESHOLD || (NETWORK === 'mainnet' ? '5' : '2'),
|
|
40
|
+
)
|
|
35
41
|
|
|
36
42
|
/**
|
|
37
43
|
* The key-server committee. Object ids and aggregator URLs are supplied as parallel CSV lists
|
|
38
44
|
* (index-aligned); aggregatorUrl is required for decentralized (committee-type) servers only —
|
|
39
45
|
* independent servers derive their URL from the on-chain object and do not need one.
|
|
40
46
|
*
|
|
41
|
-
*
|
|
42
|
-
* [0] Decentralized (Mysten) — requires aggregatorUrl
|
|
47
|
+
* Testnet defaults — three verified Mysten Labs servers:
|
|
48
|
+
* [0] Decentralized (Mysten aggregator) — requires aggregatorUrl
|
|
43
49
|
* [1] Independent server 1
|
|
44
50
|
* [2] Independent server 2
|
|
45
51
|
* Override via VITE_SEAL_SERVER_OBJECT_IDS_TESTNET / VITE_SEAL_AGGREGATOR_URLS_TESTNET.
|
|
52
|
+
*
|
|
53
|
+
* Mainnet defaults — Mysten Labs 5-of-8 decentralized committee:
|
|
54
|
+
* Committee object: 0x686098f1439237fff9f36b99c7329683c22979d2005c2465cb891acb012a7595
|
|
55
|
+
* Aggregator: https://seal-aggregator-mainnet.mystenlabs.com
|
|
56
|
+
* NOTE: The mainnet aggregator requires an Enoki API key (X-API-Key header).
|
|
57
|
+
* Override via VITE_SEAL_SERVER_OBJECT_IDS_MAINNET / VITE_SEAL_AGGREGATOR_URLS_MAINNET.
|
|
58
|
+
* When independent open-mode key servers become available on mainnet, they can be added here.
|
|
46
59
|
*/
|
|
47
60
|
export const SEAL_SERVERS: KeyServerConfig[] = (() => {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
const defaults: Record<Network, { ids: string[]; aggs: string[] }> = {
|
|
62
|
+
testnet: {
|
|
63
|
+
ids: [
|
|
64
|
+
'0xb012378c9f3799fb5b1a7083da74a4069e3c3f1c93de0b27212a5799ce1e1e98',
|
|
65
|
+
'0x73d05d62c18d9374e3ea529e8e0ed6161da1a141a94d3f76ae3fe4e99356db75',
|
|
66
|
+
'0xf5d14a81a982144ae441cd7d64b09027f116a468bd36e7eca494f750591623c8',
|
|
67
|
+
],
|
|
68
|
+
aggs: ['https://seal-aggregator-testnet.mystenlabs.com'],
|
|
69
|
+
},
|
|
70
|
+
mainnet: {
|
|
71
|
+
ids: ['0x686098f1439237fff9f36b99c7329683c22979d2005c2465cb891acb012a7595'],
|
|
72
|
+
aggs: ['https://seal-aggregator-mainnet.mystenlabs.com'],
|
|
73
|
+
},
|
|
74
|
+
}
|
|
54
75
|
|
|
55
76
|
const envIds = csv(netEnv('VITE_SEAL_SERVER_OBJECT_IDS'))
|
|
56
77
|
const envAggs = csv(netEnv('VITE_SEAL_AGGREGATOR_URLS'))
|
|
57
|
-
const ids = envIds.length > 0 ? envIds :
|
|
58
|
-
const aggs = envAggs.length > 0 ? envAggs :
|
|
78
|
+
const ids = envIds.length > 0 ? envIds : defaults[NETWORK].ids
|
|
79
|
+
const aggs = envAggs.length > 0 ? envAggs : defaults[NETWORK].aggs
|
|
59
80
|
return ids.map((objectId, i) => ({ objectId, weight: 1, aggregatorUrl: aggs[i] }))
|
|
60
81
|
})()
|
|
61
82
|
|
|
@@ -75,11 +96,12 @@ export const WALRUS_AGGREGATOR: string =
|
|
|
75
96
|
/** Default blob lifetime (Walrus storage epochs). */
|
|
76
97
|
export const WALRUS_EPOCHS = Number(env.VITE_WALRUS_EPOCHS || '5')
|
|
77
98
|
|
|
78
|
-
/**
|
|
79
|
-
* Seal committee mode is testnet-only today. On mainnet the app shows a "pending" notice and
|
|
80
|
-
* disables sealing until the committee is available there.
|
|
81
|
-
*/
|
|
82
|
-
export const MAINNET_PENDING = NETWORK === 'mainnet'
|
|
83
|
-
|
|
84
99
|
/** True when the on-chain policy package + committee are configured for the active network. */
|
|
85
100
|
export const SEAL_CONFIGURED = Boolean(SEAL_PACKAGE_ID) && SEAL_SERVERS.length > 0
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* True when the active network has no Seal committee configured (empty package ID or no servers).
|
|
104
|
+
* On mainnet, populate VITE_SEAL_PACKAGE_ID_MAINNET + VITE_SEAL_SERVER_OBJECT_IDS_MAINNET +
|
|
105
|
+
* VITE_SEAL_AGGREGATOR_URLS_MAINNET to enable sealing — no code change required.
|
|
106
|
+
*/
|
|
107
|
+
export const MAINNET_PENDING = !SEAL_CONFIGURED
|