diff --git a/src/components/pages/dashboard/ManageDomain/cmp.tsx b/src/components/pages/dashboard/ManageDomain/cmp.tsx index c0c1fb9e..d111d579 100644 --- a/src/components/pages/dashboard/ManageDomain/cmp.tsx +++ b/src/components/pages/dashboard/ManageDomain/cmp.tsx @@ -180,7 +180,10 @@ export default function ManageDomain() { {domain.name}.program.public.aleph.sh. )} - {domain.target == EntityDomainType.Instance && ( + {[ + EntityDomainType.Instance, + EntityDomainType.Confidential, + ].includes(domain.target) && ( {domain.name}.instance.public.aleph.sh. @@ -278,9 +281,11 @@ export default function ManageDomain() { href={ (domain.target === 'instance' ? '/computing/instance/' - : domain.target === 'program' - ? '/computing/function/' - : '/storage/volume/') + refEntity.id + : domain.target === 'confidential' + ? '/computing/confidential/' + : domain.target === 'program' + ? '/computing/function/' + : '/storage/volume/') + refEntity.id } > Details diff --git a/src/components/pages/settings/NewDomainPage/cmp.tsx b/src/components/pages/settings/NewDomainPage/cmp.tsx index f6da4cc6..4d44edf0 100644 --- a/src/components/pages/settings/NewDomainPage/cmp.tsx +++ b/src/components/pages/settings/NewDomainPage/cmp.tsx @@ -35,7 +35,9 @@ export default function NewDomain() { const labelResourceType = targetCtrl.field.value == EntityDomainType.Instance ? 'instance' - : 'function' + : targetCtrl.field.value == EntityDomainType.Confidential + ? 'confidential' + : 'function' const onTabChange = (tabId: string) => { setRef('') @@ -43,7 +45,7 @@ export default function NewDomain() { if (['website', 'ipfs'].includes(tabId)) { setTarget(EntityDomainType.IPFS) } else { - setTarget(EntityDomainType.Instance) + setTarget(EntityDomainType.Program) } } @@ -150,13 +152,19 @@ export default function NewDomain() { label="Choose resource type" direction="row" > + {entities.length > 0 ? ( diff --git a/src/domain/confidential.ts b/src/domain/confidential.ts index ec4442f7..646dd75b 100644 --- a/src/domain/confidential.ts +++ b/src/domain/confidential.ts @@ -1,13 +1,18 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ import { Account } from '@aleph-sdk/account' import { InstanceContent, MessageType } from '@aleph-sdk/message' -import { defaultInstanceChannel, EntityType } from '@/helpers/constants' +import { + CheckoutStepType, + defaultInstanceChannel, + EntityType, +} from '@/helpers/constants' import { getDate, getExplorerURL } from '@/helpers/utils' import { ExecutableManager, ExecutableStatus } from './executable' import { FileManager } from './file' import { SSHKeyManager } from './ssh' import { VolumeManager } from './volume' import { DomainManager } from './domain' -import { ReadOnlyEntityManager } from './types' +import { EntityManager } from './types' import { instanceSchema, instanceStreamSchema, @@ -33,7 +38,7 @@ export type Confidential = InstanceContent & { export class ConfidentialManager extends ExecutableManager - implements ReadOnlyEntityManager + implements EntityManager { static addSchema = instanceSchema static addStreamSchema = instanceStreamSchema @@ -51,6 +56,32 @@ export class ConfidentialManager super(account, volumeManager, domainManager, nodeManager, sdkClient) } + add(entity: unknown): Promise { + throw new Error('Method not implemented.') + } + del(entityOrId: string | Confidential): Promise { + throw new Error('Method not implemented.') + } + getAddSteps(entity: unknown): Promise { + throw new Error('Method not implemented.') + } + addSteps( + entity: unknown, + ): AsyncGenerator { + throw new Error('Method not implemented.') + } + getDelSteps( + entity: string | Confidential | (string | Confidential)[], + ): Promise { + throw new Error('Method not implemented.') + } + delSteps( + entity: string | Confidential | (string | Confidential)[], + extra?: any, + ): AsyncGenerator { + throw new Error('Method not implemented.') + } + async getAll(): Promise { try { const response = await this.sdkClient.getMessages({ diff --git a/src/domain/domain.ts b/src/domain/domain.ts index 47682374..d77fb135 100644 --- a/src/domain/domain.ts +++ b/src/domain/domain.ts @@ -89,16 +89,22 @@ export class DomainManager implements EntityManager { } async retry(domain: Domain) { + const isConfidential = domain.target == EntityDomainType.Confidential + const type = isConfidential ? EntityDomainType.Instance : domain.target const content: DomainAggregate = { [domain.name]: { message_id: domain.ref, - type: domain.target, + type, updated_at: new Date().toISOString(), - ...(domain.target === EntityDomainType.IPFS + ...(type === EntityDomainType.IPFS ? { options: { catch_all_path: '/404.html' }, } - : {}), + : isConfidential + ? { + options: { confidential: true }, + } + : {}), }, } @@ -143,15 +149,21 @@ export class DomainManager implements EntityManager { try { const content: DomainAggregate = domains.reduce((ac, cv) => { const { name, ref, target } = cv + const isConfidential = target == EntityDomainType.Confidential + const type = isConfidential ? EntityDomainType.Instance : target ac[name] = { message_id: ref, - type: target, + type, updated_at: new Date().toISOString(), - ...(target === EntityDomainType.IPFS + ...(type === EntityDomainType.IPFS ? { options: { catch_all_path: '/404.html' }, } - : {}), + : isConfidential + ? { + options: { confidential: true }, + } + : {}), } return ac }, {} as DomainAggregate) @@ -200,7 +212,10 @@ export class DomainManager implements EntityManager { body: JSON.stringify({ name: domain.name, owner: this.account.address, - target: domain.target, + target: + domain.target == EntityDomainType.Confidential + ? EntityDomainType.Instance + : domain.target, }), }) const response = await query.json() @@ -274,13 +289,18 @@ export class DomainManager implements EntityManager { name: string, content: DomainAggregateItem, ): Domain { - const { message_id, type, updated_at } = content + const { message_id, type, updated_at, options } = content + const target = options?.['confidential'] + ? EntityDomainType.Confidential + : type const ref_path = - type === EntityDomainType.Instance - ? 'computing/instance' - : type === EntityDomainType.Program - ? 'computing/function' - : 'storage/volume' + type === EntityDomainType.Program + ? 'computing/function' + : type === EntityDomainType.Instance + ? 'computing/instance' + : type === EntityDomainType.Confidential + ? 'computing/confidential' + : 'storage/volume' let date = '-' try { date = updated_at?.slice(0, 19).replace('T', ' ') || '-' @@ -289,7 +309,7 @@ export class DomainManager implements EntityManager { type: EntityType.Domain, id: name, name, - target: type, + target, ref: message_id, confirmed: true, updated_at: date, diff --git a/src/helpers/constants.ts b/src/helpers/constants.ts index 5fa938b7..816ad74c 100644 --- a/src/helpers/constants.ts +++ b/src/helpers/constants.ts @@ -55,6 +55,7 @@ export const defaultInstanceChannel = defaultConsoleChannel export const defaultProgramChannel = defaultConsoleChannel export const defaultDomainChannel = defaultConsoleChannel export const defaultWebsiteChannel = defaultConsoleChannel +export const defaultConfidentialChannel = defaultConsoleChannel export enum EntityType { Volume = 'volume', @@ -64,6 +65,7 @@ export enum EntityType { Domain = 'domain', Indexer = 'indexer', Website = 'website', + Confidential = 'confidential', } type CheckoutAddStepType = @@ -104,12 +106,14 @@ export enum EntityDomainType { IPFS = 'ipfs', Program = 'program', Instance = 'instance', + Confidential = 'confidential', } export const EntityDomainTypeName: Record = { [EntityDomainType.IPFS]: 'IPFS', [EntityDomainType.Program]: 'Function', [EntityDomainType.Instance]: 'Instance', + [EntityDomainType.Confidential]: 'Confidential', } export enum VolumeType { @@ -126,12 +130,14 @@ export const EntityTypeName: Record = { [EntityType.Domain]: 'Domain', [EntityType.Indexer]: 'Indexer', [EntityType.Website]: 'Website', + [EntityType.Confidential]: 'Confidential', } export const EntityTypeUrlSection: Record = { [EntityType.Volume]: 'storage', [EntityType.Program]: 'computing', [EntityType.Instance]: 'computing', + [EntityType.Confidential]: 'computing', [EntityType.SSHKey]: 'settings', [EntityType.Domain]: 'settings', [EntityType.Indexer]: 'tools', @@ -146,6 +152,7 @@ export const EntityTypeSlug: Record = { [EntityType.Domain]: 'domain', [EntityType.Indexer]: 'indexer', [EntityType.Website]: 'website', + [EntityType.Confidential]: 'confidential', } export enum IndexerBlockchain { diff --git a/src/helpers/schemas/base.ts b/src/helpers/schemas/base.ts index 20d0391a..e344ab53 100644 --- a/src/helpers/schemas/base.ts +++ b/src/helpers/schemas/base.ts @@ -92,6 +92,7 @@ export const ipfsCIDSchema = requiredStringSchema.regex( export const targetSchema = z.enum([ EntityDomainType.Instance, + EntityDomainType.Confidential, EntityDomainType.Program, EntityDomainType.IPFS, ]) diff --git a/src/helpers/utils.ts b/src/helpers/utils.ts index 41e81a3f..6d341e56 100644 --- a/src/helpers/utils.ts +++ b/src/helpers/utils.ts @@ -268,10 +268,14 @@ export const isVolume = (msg: AnyMessage) => msg.type === MessageType.store export const isProgram = (msg: AnyMessage) => msg.type === MessageType.program export const isInstance = (msg: AnyMessage) => msg.type === MessageType.instance export const isSSHKey = (msg: AnyMessage) => msg.type === MessageType.post +export const isConfidential = (msg: AnyMessage) => + msg.type === MessageType.instance && + (msg.content as any)?.environment?.trusted_execution?.firmware.length == 64 export function getEntityTypeFromMessage(msg: AnyMessage): EntityType { if (isVolume(msg)) return EntityType.Volume if (isProgram(msg)) return EntityType.Program + if (isConfidential(msg)) return EntityType.Confidential if (isInstance(msg)) return EntityType.Instance if (isSSHKey(msg)) return EntityType.SSHKey throw Err.UnknownType diff --git a/src/hooks/common/useManager/useEntityManager.ts b/src/hooks/common/useManager/useEntityManager.ts index 861fdf06..b6d460d4 100644 --- a/src/hooks/common/useManager/useEntityManager.ts +++ b/src/hooks/common/useManager/useEntityManager.ts @@ -15,6 +15,7 @@ export function useEntityManager( instanceManager, indexerManager, websiteManager, + confidentialManager, } = appState.manager const entityMap: Record< @@ -29,6 +30,7 @@ export function useEntityManager( [EntityType.Program]: programManager, [EntityType.Indexer]: indexerManager, [EntityType.Website]: websiteManager, + [EntityType.Confidential]: confidentialManager, } }, [ domainManager, @@ -38,6 +40,7 @@ export function useEntityManager( volumeManager, indexerManager, websiteManager, + confidentialManager, ]) if (!type) return diff --git a/src/hooks/pages/settings/useNewDomainPage.ts b/src/hooks/pages/settings/useNewDomainPage.ts index 99a21f00..c068b4db 100644 --- a/src/hooks/pages/settings/useNewDomainPage.ts +++ b/src/hooks/pages/settings/useNewDomainPage.ts @@ -54,6 +54,7 @@ export function useNewDomainPage(): UseNewDomainPageReturn { instance: { entities: instances }, program: { entities: programs }, website: { entities: websites }, + confidential: { entities: confidentials }, }, dispatch, ] = useAppState() @@ -141,7 +142,11 @@ export function useNewDomainPage(): UseNewDomainPageReturn { if (!entityType) return [] if (entityType !== EntityDomainType.IPFS) { const entities = - entityType === EntityDomainType.Instance ? instances : programs + entityType === EntityDomainType.Instance + ? instances + : entityType === EntityDomainType.Confidential + ? confidentials + : programs return (entities || []).map(({ id, metadata }) => { return { label: (metadata?.name as string | undefined) || id, @@ -157,11 +162,15 @@ export function useNewDomainPage(): UseNewDomainPageReturn { type: entityType, } }) - }, [entityType, instances, programs, websites]) + }, [entityType, instances, programs, websites, confidentials]) const hasInstances = useMemo(() => !!instances?.length, [instances]) const hasFunctions = useMemo(() => !!programs?.length, [programs]) const hasWebsites = useMemo(() => !!websites?.length, [websites]) + const hasConfidentials = useMemo( + () => !!confidentials?.length, + [confidentials], + ) /* const hasEntities = useMemo( () => hasInstances || hasFunctions || hasWebsites, [hasFunctions, hasInstances, hasWebsites], @@ -170,12 +179,24 @@ export function useNewDomainPage(): UseNewDomainPageReturn { useEffect(() => { if (entityType === EntityDomainType.Instance && hasInstances) { setValue('target', EntityDomainType.Instance) + } else if ( + entityType === EntityDomainType.Confidential && + hasConfidentials + ) { + setValue('target', EntityDomainType.Confidential) } else if (entityType === EntityDomainType.Program && hasFunctions) { setValue('target', EntityDomainType.Program) } else if (entityType === EntityDomainType.IPFS) { setValue('target', EntityDomainType.IPFS) } - }, [entityType, hasFunctions, hasInstances, hasWebsites, setValue]) + }, [ + entityType, + hasFunctions, + hasInstances, + hasConfidentials, + hasWebsites, + setValue, + ]) const setTarget = (target: EntityDomainType) => { setValue('target', target) diff --git a/src/hooks/pages/solutions/manage/useManageDomain.ts b/src/hooks/pages/solutions/manage/useManageDomain.ts index 6a3caa4b..a15bb7ef 100644 --- a/src/hooks/pages/solutions/manage/useManageDomain.ts +++ b/src/hooks/pages/solutions/manage/useManageDomain.ts @@ -17,6 +17,7 @@ import { useCheckoutNotification, } from '@/hooks/form/useCheckoutNotification' import Err from '@/helpers/errors' +import { Confidential } from '@/domain/confidential' export type ManageDomain = { domain?: Domain @@ -47,6 +48,7 @@ export function useManageDomain(): ManageDomain { const refEntity = useHashToEntity(domain?.ref) as | Program | Instance + | Confidential | Volume | undefined diff --git a/src/store/entity.ts b/src/store/entity.ts index 8de295d3..c5ebc7e7 100644 --- a/src/store/entity.ts +++ b/src/store/entity.ts @@ -82,6 +82,7 @@ export type EntityReducer = StoreReducer, EntityAction> export function getEntityReducer( name: string, key: K, + // eslint-disable-next-line @typescript-eslint/no-unused-vars virtualKey?: K, ): EntityReducer { return (state = initialState, action) => {