@tangle-network/blueprint-ui 0.1.0 → 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/README.md +47 -11
- package/dist/BlueprintHostPanel-6iVEh-f1.d.ts +39 -0
- package/dist/chunk-37ADATBT.js +55 -0
- package/dist/chunk-37ADATBT.js.map +1 -0
- package/dist/chunk-A6PJT5YQ.js +1180 -0
- package/dist/chunk-A6PJT5YQ.js.map +1 -0
- package/dist/chunk-GD3AZEJL.js +327 -0
- package/dist/chunk-GD3AZEJL.js.map +1 -0
- package/dist/components.d.ts +179 -0
- package/dist/components.js +1127 -0
- package/dist/components.js.map +1 -0
- package/dist/host.d.ts +96 -0
- package/dist/host.js +39 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +8470 -0
- package/dist/index.js +841 -0
- package/dist/index.js.map +1 -0
- package/dist/preset.d.ts +60 -0
- package/dist/preset.js +7 -0
- package/dist/preset.js.map +1 -0
- package/dist/registry-JhwB9BPD.d.ts +87 -0
- package/dist/styles.css +559 -0
- package/package.json +42 -13
- package/src/components/layout/AppDocument.tsx +1 -1
- package/src/components/layout/ChainSwitcher.tsx +27 -10
- package/src/components/layout/Web3Shell.tsx +81 -6
- package/src/components/web3/ConnectWalletCta.tsx +21 -0
- package/src/components.ts +6 -0
- package/src/contracts/abi.ts +10 -1
- package/src/contracts/chains.ts +23 -10
- package/src/contracts/publicClient.ts +52 -10
- package/src/hooks/useOperators.ts +203 -96
- package/src/hooks/useProvisionProgress.ts +2 -1
- package/src/hooks/useQuotes.ts +69 -14
- package/src/hooks/useSessionAuth.ts +2 -1
- package/src/hooks/useSidecarAuth.ts +173 -0
- package/src/hooks/useWagmiSidecarAuth.ts +11 -0
- package/src/hooks/useWalletEthBalance.ts +68 -0
- package/src/host/components/BlueprintHostHero.tsx +91 -0
- package/src/host/components/BlueprintHostPanel.tsx +24 -0
- package/src/host/index.ts +42 -0
- package/src/host/resolver.ts +204 -0
- package/src/host/types.ts +111 -0
- package/src/index.ts +48 -2
- package/src/stores/infra.ts +3 -2
- package/src/styles.css +128 -0
- package/src/utils/env.ts +22 -0
- package/src/utils/web3.ts +9 -3
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
const WEI_PER_ETH = 1_000_000_000_000_000_000n;
|
|
4
|
+
const DISPLAY_SCALE = 1_000n; // 3 decimal places
|
|
5
|
+
|
|
6
|
+
function formatEthBalance(wei: bigint): string {
|
|
7
|
+
const whole = wei / WEI_PER_ETH;
|
|
8
|
+
const fraction = ((wei % WEI_PER_ETH) * DISPLAY_SCALE) / WEI_PER_ETH;
|
|
9
|
+
return `${whole.toString()}.${fraction.toString().padStart(3, '0')}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface UseWalletEthBalanceOptions {
|
|
13
|
+
address?: string;
|
|
14
|
+
refreshKey?: number | string;
|
|
15
|
+
readBalance: (address: string) => Promise<bigint>;
|
|
16
|
+
pollMs?: number;
|
|
17
|
+
onError?: (error: unknown) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface UseWalletEthBalanceResult {
|
|
21
|
+
balance: string | null;
|
|
22
|
+
hasError: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function useWalletEthBalance({
|
|
26
|
+
address,
|
|
27
|
+
refreshKey,
|
|
28
|
+
readBalance,
|
|
29
|
+
pollMs = 15_000,
|
|
30
|
+
onError,
|
|
31
|
+
}: UseWalletEthBalanceOptions): UseWalletEthBalanceResult {
|
|
32
|
+
const [balance, setBalance] = useState<string | null>(null);
|
|
33
|
+
const [hasError, setHasError] = useState(false);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!address) {
|
|
37
|
+
setBalance(null);
|
|
38
|
+
setHasError(false);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let cancelled = false;
|
|
43
|
+
|
|
44
|
+
const fetchBalance = () => {
|
|
45
|
+
readBalance(address)
|
|
46
|
+
.then((wei) => {
|
|
47
|
+
if (cancelled) return;
|
|
48
|
+
setBalance(formatEthBalance(wei));
|
|
49
|
+
setHasError(false);
|
|
50
|
+
})
|
|
51
|
+
.catch((error: unknown) => {
|
|
52
|
+
if (cancelled) return;
|
|
53
|
+
setHasError(true);
|
|
54
|
+
onError?.(error);
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
fetchBalance();
|
|
59
|
+
const interval = setInterval(fetchBalance, pollMs);
|
|
60
|
+
|
|
61
|
+
return () => {
|
|
62
|
+
cancelled = true;
|
|
63
|
+
clearInterval(interval);
|
|
64
|
+
};
|
|
65
|
+
}, [address, refreshKey, readBalance, pollMs, onError]);
|
|
66
|
+
|
|
67
|
+
return { balance, hasError };
|
|
68
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '../../components/ui/card';
|
|
3
|
+
import { Badge } from '../../components/ui/badge';
|
|
4
|
+
import { Button } from '../../components/ui/button';
|
|
5
|
+
import { cn } from '../../utils';
|
|
6
|
+
|
|
7
|
+
type Action = {
|
|
8
|
+
label: string;
|
|
9
|
+
href?: string;
|
|
10
|
+
onClick?: () => void;
|
|
11
|
+
variant?: React.ComponentProps<typeof Button>['variant'];
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type BlueprintHostHeroProps = {
|
|
16
|
+
title: string;
|
|
17
|
+
tagline?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
badges?: string[];
|
|
20
|
+
actions?: Action[];
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
className?: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export function BlueprintHostHero({
|
|
26
|
+
title,
|
|
27
|
+
tagline,
|
|
28
|
+
description,
|
|
29
|
+
badges = [],
|
|
30
|
+
actions = [],
|
|
31
|
+
children,
|
|
32
|
+
className,
|
|
33
|
+
}: BlueprintHostHeroProps) {
|
|
34
|
+
return (
|
|
35
|
+
<Card className={cn('rounded-3xl border-bp-elements-borderColor/70 bg-bp-elements-background-depth-2', className)}>
|
|
36
|
+
<CardHeader className="space-y-4">
|
|
37
|
+
{badges.length > 0 ? (
|
|
38
|
+
<div className="flex flex-wrap gap-2">
|
|
39
|
+
{badges.map((badge) => (
|
|
40
|
+
<Badge key={badge} variant="secondary">
|
|
41
|
+
{badge}
|
|
42
|
+
</Badge>
|
|
43
|
+
))}
|
|
44
|
+
</div>
|
|
45
|
+
) : null}
|
|
46
|
+
<div className="space-y-2">
|
|
47
|
+
<CardTitle className="text-3xl">{title}</CardTitle>
|
|
48
|
+
{tagline ? (
|
|
49
|
+
<CardDescription className="text-base text-bp-elements-textPrimary/80">
|
|
50
|
+
{tagline}
|
|
51
|
+
</CardDescription>
|
|
52
|
+
) : null}
|
|
53
|
+
</div>
|
|
54
|
+
{description ? (
|
|
55
|
+
<p className="max-w-3xl text-sm leading-6 text-bp-elements-textSecondary">
|
|
56
|
+
{description}
|
|
57
|
+
</p>
|
|
58
|
+
) : null}
|
|
59
|
+
</CardHeader>
|
|
60
|
+
{(actions.length > 0 || children) && (
|
|
61
|
+
<CardContent className="space-y-4">
|
|
62
|
+
{actions.length > 0 ? (
|
|
63
|
+
<div className="flex flex-wrap gap-3">
|
|
64
|
+
{actions.map((action) => {
|
|
65
|
+
const button = (
|
|
66
|
+
<Button
|
|
67
|
+
key={action.label}
|
|
68
|
+
variant={action.variant ?? 'default'}
|
|
69
|
+
onClick={action.onClick}
|
|
70
|
+
disabled={action.disabled}
|
|
71
|
+
>
|
|
72
|
+
{action.label}
|
|
73
|
+
</Button>
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return action.href ? (
|
|
77
|
+
<a key={action.label} href={action.href}>
|
|
78
|
+
{button}
|
|
79
|
+
</a>
|
|
80
|
+
) : (
|
|
81
|
+
button
|
|
82
|
+
);
|
|
83
|
+
})}
|
|
84
|
+
</div>
|
|
85
|
+
) : null}
|
|
86
|
+
{children}
|
|
87
|
+
</CardContent>
|
|
88
|
+
)}
|
|
89
|
+
</Card>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Card, CardContent, CardHeader, CardTitle } from '../../components/ui/card';
|
|
3
|
+
import { cn } from '../../utils';
|
|
4
|
+
|
|
5
|
+
export type BlueprintHostPanelProps = {
|
|
6
|
+
title: string;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function BlueprintHostPanel({
|
|
12
|
+
title,
|
|
13
|
+
children,
|
|
14
|
+
className,
|
|
15
|
+
}: BlueprintHostPanelProps) {
|
|
16
|
+
return (
|
|
17
|
+
<Card className={cn('rounded-3xl border-bp-elements-borderColor/70 bg-bp-elements-background-depth-2', className)}>
|
|
18
|
+
<CardHeader>
|
|
19
|
+
<CardTitle className="text-xl">{title}</CardTitle>
|
|
20
|
+
</CardHeader>
|
|
21
|
+
<CardContent>{children}</CardContent>
|
|
22
|
+
</Card>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
BlueprintAppVisibility,
|
|
3
|
+
BlueprintPublisherVerification,
|
|
4
|
+
BlueprintExperienceTier,
|
|
5
|
+
BlueprintSlugPolicy,
|
|
6
|
+
BlueprintUiSurface,
|
|
7
|
+
BlueprintResourceRoute,
|
|
8
|
+
BlueprintPermissionScope,
|
|
9
|
+
BlueprintExternalAppMode,
|
|
10
|
+
BlueprintExternalAppTrust,
|
|
11
|
+
BlueprintPublisher,
|
|
12
|
+
BlueprintResourceModel,
|
|
13
|
+
BlueprintPermissionDescriptor,
|
|
14
|
+
BlueprintExternalAppConfig,
|
|
15
|
+
BlueprintUiManifest,
|
|
16
|
+
BlueprintAppModuleBinding,
|
|
17
|
+
BlueprintAppEntry,
|
|
18
|
+
BlueprintAppResolvedView,
|
|
19
|
+
} from './types';
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
buildCanonicalBlueprintSlug,
|
|
23
|
+
resolveBlueprintAppView,
|
|
24
|
+
toBlueprintAppEntry,
|
|
25
|
+
getBlueprintExperienceTierLabel,
|
|
26
|
+
getBlueprintSlugPolicyLabel,
|
|
27
|
+
getBlueprintSurfaceLabel,
|
|
28
|
+
getBlueprintPublisherVerificationLabel,
|
|
29
|
+
getExternalAppTrustLabel,
|
|
30
|
+
isVerifiedBlueprintPublisher,
|
|
31
|
+
canPublisherClaimSlug,
|
|
32
|
+
isTrustedExternalAppHost,
|
|
33
|
+
getBlueprintPath,
|
|
34
|
+
getBlueprintServicePath,
|
|
35
|
+
sanitizeBlueprintSlugPart,
|
|
36
|
+
deriveBlueprintRequestedSlug,
|
|
37
|
+
} from './resolver';
|
|
38
|
+
|
|
39
|
+
export type { BlueprintHostHeroProps } from './components/BlueprintHostHero';
|
|
40
|
+
export { BlueprintHostHero } from './components/BlueprintHostHero';
|
|
41
|
+
export type { BlueprintHostPanelProps } from './components/BlueprintHostPanel';
|
|
42
|
+
export { BlueprintHostPanel } from './components/BlueprintHostPanel';
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BlueprintAppEntry,
|
|
3
|
+
BlueprintAppResolvedView,
|
|
4
|
+
BlueprintExperienceTier,
|
|
5
|
+
BlueprintExternalAppTrust,
|
|
6
|
+
BlueprintPublisher,
|
|
7
|
+
BlueprintPublisherVerification,
|
|
8
|
+
BlueprintSlugPolicy,
|
|
9
|
+
BlueprintUiSurface,
|
|
10
|
+
} from './types';
|
|
11
|
+
|
|
12
|
+
const EXPERIENCE_TIER_LABELS: Record<BlueprintExperienceTier, string> = {
|
|
13
|
+
generic: 'Protocol fallback',
|
|
14
|
+
declarative: 'Declarative blueprint UI',
|
|
15
|
+
'curated-module': 'Curated app module',
|
|
16
|
+
'external-app': 'External app handoff',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const SLUG_POLICY_LABELS: Record<BlueprintSlugPolicy, string> = {
|
|
20
|
+
reserved: 'Reserved slug',
|
|
21
|
+
'publisher-scoped': 'Publisher-scoped slug',
|
|
22
|
+
'public-requested': 'Public requested slug',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const SURFACE_LABELS: Record<BlueprintUiSurface, string> = {
|
|
26
|
+
'generic-overview': 'Generic overview',
|
|
27
|
+
'service-explorer': 'Service explorer',
|
|
28
|
+
'service-console': 'Service console',
|
|
29
|
+
'actions-panel': 'Actions panel',
|
|
30
|
+
resources: 'Resources',
|
|
31
|
+
chat: 'Chat',
|
|
32
|
+
vaults: 'Vaults',
|
|
33
|
+
metrics: 'Metrics',
|
|
34
|
+
permissions: 'Permissions',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const PUBLISHER_VERIFICATION_LABELS: Record<
|
|
38
|
+
BlueprintPublisherVerification,
|
|
39
|
+
string
|
|
40
|
+
> = {
|
|
41
|
+
'first-party': 'First-party publisher',
|
|
42
|
+
verified: 'Verified publisher',
|
|
43
|
+
unverified: 'Unverified publisher',
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const EXTERNAL_APP_TRUST_LABELS: Record<BlueprintExternalAppTrust, string> = {
|
|
47
|
+
trusted: 'Trusted external app',
|
|
48
|
+
restricted: 'Restricted external app',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export function buildCanonicalBlueprintSlug(entry: BlueprintAppEntry): string {
|
|
52
|
+
if (entry.canonicalSlug) {
|
|
53
|
+
return entry.canonicalSlug;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (entry.slugPolicy === 'reserved' || !entry.publisher.namespace) {
|
|
57
|
+
return entry.slug;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return `@${entry.publisher.namespace}/${entry.slug}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function resolveBlueprintAppView(
|
|
64
|
+
entry: BlueprintAppEntry,
|
|
65
|
+
): BlueprintAppResolvedView {
|
|
66
|
+
return {
|
|
67
|
+
slug: entry.slug,
|
|
68
|
+
canonicalSlug: buildCanonicalBlueprintSlug(entry),
|
|
69
|
+
blueprintId: entry.blueprintId,
|
|
70
|
+
publisher: entry.publisher,
|
|
71
|
+
tier: entry.tier,
|
|
72
|
+
slugPolicy: entry.slugPolicy,
|
|
73
|
+
manifest: entry.manifest,
|
|
74
|
+
module: entry.module,
|
|
75
|
+
fallbackEnabled: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function toBlueprintAppEntry(
|
|
80
|
+
view: BlueprintAppResolvedView,
|
|
81
|
+
): BlueprintAppEntry {
|
|
82
|
+
return {
|
|
83
|
+
slug: view.slug,
|
|
84
|
+
canonicalSlug: view.canonicalSlug,
|
|
85
|
+
blueprintId: view.blueprintId,
|
|
86
|
+
publisher: view.publisher,
|
|
87
|
+
tier: view.tier,
|
|
88
|
+
slugPolicy: view.slugPolicy,
|
|
89
|
+
manifest: view.manifest,
|
|
90
|
+
module: view.module,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function getBlueprintExperienceTierLabel(
|
|
95
|
+
tier: BlueprintExperienceTier,
|
|
96
|
+
): string {
|
|
97
|
+
return EXPERIENCE_TIER_LABELS[tier];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function getBlueprintSlugPolicyLabel(policy: BlueprintSlugPolicy): string {
|
|
101
|
+
return SLUG_POLICY_LABELS[policy];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function getBlueprintSurfaceLabel(surface: BlueprintUiSurface): string {
|
|
105
|
+
return SURFACE_LABELS[surface];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function getBlueprintPublisherVerificationLabel(
|
|
109
|
+
verification: BlueprintPublisherVerification,
|
|
110
|
+
): string {
|
|
111
|
+
return PUBLISHER_VERIFICATION_LABELS[verification];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function getExternalAppTrustLabel(
|
|
115
|
+
trust: BlueprintExternalAppTrust,
|
|
116
|
+
): string {
|
|
117
|
+
return EXTERNAL_APP_TRUST_LABELS[trust];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function isVerifiedBlueprintPublisher(
|
|
121
|
+
publisher: BlueprintPublisher,
|
|
122
|
+
): boolean {
|
|
123
|
+
return (
|
|
124
|
+
publisher.verification === 'first-party' ||
|
|
125
|
+
publisher.verification === 'verified'
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function canPublisherClaimSlug(
|
|
130
|
+
slug: string,
|
|
131
|
+
publisher?: Pick<BlueprintPublisher, 'namespace' | 'verification'>,
|
|
132
|
+
reservedSlugs: Set<string> = new Set(),
|
|
133
|
+
): boolean {
|
|
134
|
+
if (reservedSlugs.has(slug)) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
publisher?.namespace !== undefined &&
|
|
140
|
+
publisher.namespace.trim().length > 0 &&
|
|
141
|
+
(publisher.verification === 'verified' ||
|
|
142
|
+
publisher.verification === 'first-party')
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function isTrustedExternalAppHost(
|
|
147
|
+
host: string,
|
|
148
|
+
trustedHosts: readonly string[] = [],
|
|
149
|
+
): boolean {
|
|
150
|
+
const normalizedHost = host.trim().toLowerCase();
|
|
151
|
+
|
|
152
|
+
return trustedHosts.some(
|
|
153
|
+
(trustedHost) =>
|
|
154
|
+
normalizedHost === trustedHost || normalizedHost.endsWith(`.${trustedHost}`),
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function getBlueprintPath(view: BlueprintAppResolvedView): string {
|
|
159
|
+
if (view.tier === 'curated-module' || view.tier === 'external-app') {
|
|
160
|
+
return `/blueprints/${view.canonicalSlug}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (view.blueprintId !== undefined) {
|
|
164
|
+
return `/blueprints/${view.blueprintId.toString()}`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return `/blueprints/${view.slug}`;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function getBlueprintServicePath(
|
|
171
|
+
view: BlueprintAppResolvedView,
|
|
172
|
+
serviceId: string,
|
|
173
|
+
): string {
|
|
174
|
+
if (view.tier === 'curated-module' || view.tier === 'external-app') {
|
|
175
|
+
return `${getBlueprintPath(view)}/${serviceId}`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return `${getBlueprintPath(view)}/services/${serviceId}`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function sanitizeBlueprintSlugPart(value: string): string {
|
|
182
|
+
return value
|
|
183
|
+
.trim()
|
|
184
|
+
.toLowerCase()
|
|
185
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
186
|
+
.replace(/^-+|-+$/g, '')
|
|
187
|
+
.replace(/-{2,}/g, '-');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function deriveBlueprintRequestedSlug(
|
|
191
|
+
blueprint: Pick<{ name: string; author: string; id: bigint }, 'name' | 'author' | 'id'>,
|
|
192
|
+
): string {
|
|
193
|
+
const fromName = sanitizeBlueprintSlugPart(blueprint.name);
|
|
194
|
+
if (fromName.length > 0) {
|
|
195
|
+
return fromName;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const fromAuthor = sanitizeBlueprintSlugPart(blueprint.author);
|
|
199
|
+
if (fromAuthor.length > 0) {
|
|
200
|
+
return `${fromAuthor}-${blueprint.id.toString()}`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return `blueprint-${blueprint.id.toString()}`;
|
|
204
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
export type BlueprintAppVisibility = 'first-party' | 'third-party';
|
|
2
|
+
|
|
3
|
+
export type BlueprintPublisherVerification =
|
|
4
|
+
| 'first-party'
|
|
5
|
+
| 'verified'
|
|
6
|
+
| 'unverified';
|
|
7
|
+
|
|
8
|
+
export type BlueprintExperienceTier =
|
|
9
|
+
| 'generic'
|
|
10
|
+
| 'declarative'
|
|
11
|
+
| 'curated-module'
|
|
12
|
+
| 'external-app';
|
|
13
|
+
|
|
14
|
+
export type BlueprintSlugPolicy =
|
|
15
|
+
| 'reserved'
|
|
16
|
+
| 'publisher-scoped'
|
|
17
|
+
| 'public-requested';
|
|
18
|
+
|
|
19
|
+
export type BlueprintUiSurface =
|
|
20
|
+
| 'generic-overview'
|
|
21
|
+
| 'service-explorer'
|
|
22
|
+
| 'service-console'
|
|
23
|
+
| 'actions-panel'
|
|
24
|
+
| 'resources'
|
|
25
|
+
| 'chat'
|
|
26
|
+
| 'vaults'
|
|
27
|
+
| 'metrics'
|
|
28
|
+
| 'permissions';
|
|
29
|
+
|
|
30
|
+
export type BlueprintResourceRoute =
|
|
31
|
+
| 'bots'
|
|
32
|
+
| 'agents'
|
|
33
|
+
| 'runs'
|
|
34
|
+
| 'vault'
|
|
35
|
+
| 'chat'
|
|
36
|
+
| 'custom';
|
|
37
|
+
|
|
38
|
+
export type BlueprintPermissionScope =
|
|
39
|
+
| 'blueprint'
|
|
40
|
+
| 'service'
|
|
41
|
+
| 'resource';
|
|
42
|
+
|
|
43
|
+
export type BlueprintExternalAppMode = 'link' | 'iframe';
|
|
44
|
+
export type BlueprintExternalAppTrust = 'trusted' | 'restricted';
|
|
45
|
+
|
|
46
|
+
export type BlueprintPublisher = {
|
|
47
|
+
label: string;
|
|
48
|
+
namespace?: string;
|
|
49
|
+
visibility: BlueprintAppVisibility;
|
|
50
|
+
verification: BlueprintPublisherVerification;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type BlueprintResourceModel = {
|
|
54
|
+
serviceNoun: string;
|
|
55
|
+
resourceNoun: string;
|
|
56
|
+
resourceRoute?: BlueprintResourceRoute;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type BlueprintPermissionDescriptor = {
|
|
60
|
+
key: string;
|
|
61
|
+
label: string;
|
|
62
|
+
scope: BlueprintPermissionScope;
|
|
63
|
+
description?: string;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type BlueprintExternalAppConfig = {
|
|
67
|
+
url: string;
|
|
68
|
+
mode: BlueprintExternalAppMode;
|
|
69
|
+
label?: string;
|
|
70
|
+
host: string;
|
|
71
|
+
trust: BlueprintExternalAppTrust;
|
|
72
|
+
reason?: string;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export type BlueprintUiManifest = {
|
|
76
|
+
displayName: string;
|
|
77
|
+
tagline: string;
|
|
78
|
+
description: string;
|
|
79
|
+
surfaces: BlueprintUiSurface[];
|
|
80
|
+
resources: BlueprintResourceModel;
|
|
81
|
+
permissions?: BlueprintPermissionDescriptor[];
|
|
82
|
+
externalApp?: BlueprintExternalAppConfig;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export type BlueprintAppModuleBinding = {
|
|
86
|
+
moduleId: string;
|
|
87
|
+
status: 'active' | 'planned';
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export type BlueprintAppEntry = {
|
|
91
|
+
slug: string;
|
|
92
|
+
canonicalSlug?: string;
|
|
93
|
+
blueprintId?: bigint;
|
|
94
|
+
publisher: BlueprintPublisher;
|
|
95
|
+
tier: BlueprintExperienceTier;
|
|
96
|
+
slugPolicy: BlueprintSlugPolicy;
|
|
97
|
+
manifest: BlueprintUiManifest;
|
|
98
|
+
module?: BlueprintAppModuleBinding;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export type BlueprintAppResolvedView = {
|
|
102
|
+
slug: string;
|
|
103
|
+
canonicalSlug: string;
|
|
104
|
+
blueprintId?: bigint;
|
|
105
|
+
publisher: BlueprintPublisher;
|
|
106
|
+
tier: BlueprintExperienceTier;
|
|
107
|
+
slugPolicy: BlueprintSlugPolicy;
|
|
108
|
+
manifest: BlueprintUiManifest;
|
|
109
|
+
module?: BlueprintAppModuleBinding;
|
|
110
|
+
fallbackEnabled: boolean;
|
|
111
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// ── Utils ──
|
|
7
7
|
export { cn } from './utils';
|
|
8
8
|
export { resolveOperatorRpc } from './utils/resolveOperatorRpc';
|
|
9
|
-
export { createTangleTransports, defaultConnectKitOptions, tangleWalletChains } from './utils/web3';
|
|
9
|
+
export { createTangleTransports, defaultConnectKitOptions, getTangleWalletChains, tangleWalletChains } from './utils/web3';
|
|
10
10
|
export { bpThemeTokens } from './preset';
|
|
11
11
|
|
|
12
12
|
// ── Stores ──
|
|
@@ -25,6 +25,7 @@ export { tangleJobsAbi, tangleServicesAbi, tangleOperatorsAbi } from './contract
|
|
|
25
25
|
export type { CoreAddresses, NetworkConfig } from './contracts/chains';
|
|
26
26
|
export {
|
|
27
27
|
resolveRpcUrl,
|
|
28
|
+
createTangleLocalChain,
|
|
28
29
|
rpcUrl,
|
|
29
30
|
tangleLocal,
|
|
30
31
|
tangleTestnet,
|
|
@@ -36,6 +37,7 @@ export {
|
|
|
36
37
|
} from './contracts/chains';
|
|
37
38
|
export {
|
|
38
39
|
selectedChainIdStore,
|
|
40
|
+
sanitizeSelectedChainId,
|
|
39
41
|
publicClientStore,
|
|
40
42
|
getPublicClient,
|
|
41
43
|
publicClient,
|
|
@@ -59,9 +61,49 @@ export {
|
|
|
59
61
|
getJobById,
|
|
60
62
|
} from './blueprints/registry';
|
|
61
63
|
|
|
64
|
+
// ── Blueprint Host ──
|
|
65
|
+
export type {
|
|
66
|
+
BlueprintAppVisibility,
|
|
67
|
+
BlueprintPublisherVerification,
|
|
68
|
+
BlueprintExperienceTier,
|
|
69
|
+
BlueprintSlugPolicy,
|
|
70
|
+
BlueprintUiSurface,
|
|
71
|
+
BlueprintResourceRoute,
|
|
72
|
+
BlueprintPermissionScope,
|
|
73
|
+
BlueprintExternalAppMode,
|
|
74
|
+
BlueprintExternalAppTrust,
|
|
75
|
+
BlueprintPublisher,
|
|
76
|
+
BlueprintResourceModel,
|
|
77
|
+
BlueprintPermissionDescriptor,
|
|
78
|
+
BlueprintExternalAppConfig,
|
|
79
|
+
BlueprintUiManifest,
|
|
80
|
+
BlueprintAppModuleBinding,
|
|
81
|
+
BlueprintAppEntry,
|
|
82
|
+
BlueprintAppResolvedView,
|
|
83
|
+
} from './host';
|
|
84
|
+
export {
|
|
85
|
+
buildCanonicalBlueprintSlug,
|
|
86
|
+
resolveBlueprintAppView,
|
|
87
|
+
toBlueprintAppEntry,
|
|
88
|
+
getBlueprintExperienceTierLabel,
|
|
89
|
+
getBlueprintSlugPolicyLabel,
|
|
90
|
+
getBlueprintSurfaceLabel,
|
|
91
|
+
getBlueprintPublisherVerificationLabel,
|
|
92
|
+
getExternalAppTrustLabel,
|
|
93
|
+
isVerifiedBlueprintPublisher,
|
|
94
|
+
canPublisherClaimSlug,
|
|
95
|
+
isTrustedExternalAppHost,
|
|
96
|
+
getBlueprintPath,
|
|
97
|
+
getBlueprintServicePath,
|
|
98
|
+
sanitizeBlueprintSlugPart,
|
|
99
|
+
deriveBlueprintRequestedSlug,
|
|
100
|
+
} from './host';
|
|
101
|
+
export type { BlueprintHostHeroProps, BlueprintHostPanelProps } from './host';
|
|
102
|
+
export { BlueprintHostHero, BlueprintHostPanel } from './host';
|
|
103
|
+
|
|
62
104
|
// ── Hooks ──
|
|
63
105
|
export type { DiscoveredOperator } from './hooks/useOperators';
|
|
64
|
-
export { useOperators } from './hooks/useOperators';
|
|
106
|
+
export { discoverOperatorsWithClient, useOperators } from './hooks/useOperators';
|
|
65
107
|
export type { JobFormState } from './hooks/useJobForm';
|
|
66
108
|
export { useJobForm } from './hooks/useJobForm';
|
|
67
109
|
export type { JobQuote, UseJobPriceResult, JobPriceEntry, UseJobPricesResult } from './hooks/useJobPrice';
|
|
@@ -77,3 +119,7 @@ export { useSessionAuth } from './hooks/useSessionAuth';
|
|
|
77
119
|
export type { ProvisionPhase, ProvisionStatus } from './hooks/useProvisionProgress';
|
|
78
120
|
export { getPhaseLabel, isTerminalPhase, useProvisionProgress } from './hooks/useProvisionProgress';
|
|
79
121
|
export { useThemeValue } from './hooks/useThemeValue';
|
|
122
|
+
export type { UseSidecarAuthOptions, SidecarAuth } from './hooks/useSidecarAuth';
|
|
123
|
+
export { useSidecarAuth } from './hooks/useSidecarAuth';
|
|
124
|
+
export { useWagmiSidecarAuth } from './hooks/useWagmiSidecarAuth';
|
|
125
|
+
export { useWalletEthBalance } from './hooks/useWalletEthBalance';
|
package/src/stores/infra.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { persistedAtom } from './persistedAtom';
|
|
2
|
+
import { getEnvVar } from '../utils/env';
|
|
2
3
|
|
|
3
|
-
const defaultBlueprintId =
|
|
4
|
-
const defaultServiceId =
|
|
4
|
+
const defaultBlueprintId = getEnvVar('VITE_BLUEPRINT_ID') ?? '0';
|
|
5
|
+
const defaultServiceId = getEnvVar('VITE_SERVICE_ID') ?? getEnvVar('VITE_SERVICE_IDS')?.split(',')[0] ?? '0';
|
|
5
6
|
|
|
6
7
|
export interface OperatorInfo {
|
|
7
8
|
address: string;
|