Skip to content
ENC Protocol

@enc-protocol/services — Protocol Services

@enc-protocol/services provides platform-agnostic protocol services that sit between a per-app SDK and the transport adapter. These services handle cross-cutting concerns like registry lookups, peer messaging, subscriptions, and enclave provisioning.

Installation

npm install @enc-protocol/services

Depends on @enc-protocol/plugin-runtime and @enc-protocol/plugin-client-base.

Package Structure

registry.js — RegistryService

Service for looking up enclaves by ID or by app owner.

RegistryService

import { RegistryService } from '@enc-protocol/services/registry.js'
 
const registry = new RegistryService(registryUrl)

.lookupEnclave(enclaveId)

await registry.lookupEnclave(enclaveId: string) → { enclaveId, appId, owner, metadata }

Resolve an enclave's metadata (app, owner, endpoints).

.lookupByOwner(ownerPubHex, appId)

await registry.lookupByOwner(ownerPubHex: string, appId: string) → Enclave[]

List all enclaves owned by an identity in a given app.

.listApps()

await registry.listApps() → { id, name, description }[]

List all registered apps.

profiles.js — ProfilesService

Service for resolving and caching identity profiles.

ProfilesService

import { ProfilesService } from '@enc-protocol/services/profiles.js'
 
const profiles = new ProfilesService(registryUrl)

.getProfile(pubHex)

await profiles.getProfile(pubHex: string) → { identity, name, bio, image_url }

Fetch a profile by public key. Returns cached result on subsequent calls.

.setProfile(identity, profile)

await profiles.setProfile(identity: Object, profile: Object) → void

Publish or update an identity's profile.

.clearCache()

profiles.clearCache() → void

Clear the in-memory profile cache.

peer-messaging.js — PeerMessagingService

Service for sending messages between app instances.

PeerMessagingService

import { PeerMessagingService } from '@enc-protocol/services/peer-messaging.js'
 
const pm = new PeerMessagingService(opts)

.send(targetPubHex, message, opts?)

await pm.send(targetPubHex: string, message: Object, opts?: Object) → void

Send a message to another identity's app instance.

.on(event, handler)

pm.on('message', (from, msg) => { /* … */ })

Listen for incoming messages.

subscriber.js — SubscriberService

Coordinates subscriptions across multiple enclaves, multiplexing into a single listener stream.

SubscriberService

import { SubscriberService } from '@enc-protocol/services/subscriber.js'
 
const sub = new SubscriberService(opts)

.add(enclaveId, filter?)

sub.add(enclaveId: string, filter?: Object) → string  // subscription ID

Add an enclave to the subscription set.

.on(event, handler)

sub.on('event', (event, enclaveId) => { /* … */ })
sub.on('eose', (enclaveId) => { /* … */ })

Listen for events across all subscribed enclaves.

.close(subId)

sub.close(subId: string) → void

Close a single subscription.

enclave-provisioner.js — EnclaveProvisionerService

Service for minting new enclaves on a node.

EnclaveProvisionerService

import { EnclaveProvisionerService } from '@enc-protocol/services/enclave-provisioner.js'
 
const provisioner = new EnclaveProvisionerService(nodeUrl)

.createEnclave(identity, manifest, opts?)

await provisioner.createEnclave(
  identity: Object,
  manifest: Object,
  opts?: { appId?: string, metadata?: Object }
) → { enclaveId, owner, app_id }

Mint a new enclave and register it with the app.

.registerEnclave(enclaveId, appId, metadata?)

await provisioner.registerEnclave(
  enclaveId: string,
  appId: string,
  metadata?: Object
) → void

Register an existing enclave with the registry.

compose-sdk.js — composeSdk

Factory function to wire services + adapter + plugins into a complete SDK.

composeSdk()

import { composeSdk } from '@enc-protocol/services/compose-sdk.js'
 
const sdk = await composeSdk({
  appId: 'personal',
  identity: { privateKey, publicKeyHex },
  adapter: memoryAdapter,
  plugins: [ratchetPairPlugin, ecdhEnvelopePlugin],
  registryUrl: 'https://registry.example.com',
  nodeUrl: 'https://node.example.com',
})

Parameters:

ParameterTypeDescription
appIdstringApp identifier
identityObjectIdentity with private key and pubkey hex
adapterObjectTransport adapter (NetworkAdapter, etc.)
pluginsObject[]Confidentiality plugins
registryUrlstringRegistry endpoint
nodeUrlstringNode endpoint (optional for memory mode)

Returns: Composed SDK with services integrated.

{
  registry: RegistryService,
  profiles: ProfilesService,
  messaging: PeerMessagingService,
  subscriber: SubscriberService,
  provisioner: EnclaveProvisionerService,
  adapter: <passed adapter>,
  identity: <passed identity>,
}

Example: Personal SDK with Services

import { composeSdk } from '@enc-protocol/services/compose-sdk.js'
import { ratchetPairPlugin } from '@enc-protocol/plugin-dm-ratchet'
import { ecdhEnvelopePlugin } from '@enc-protocol/plugin-ecdh-envelope'  // confidentiality plugins are independent packages
import { createIdentity, NetworkAdapter } from '@enc-protocol/client'
 
const identity = createIdentity()
const adapter = new NetworkAdapter('http://localhost:8787', '', identity)
 
const sdk = await composeSdk({
  appId: 'personal',
  identity,
  adapter,
  plugins: [ratchetPairPlugin, ecdhEnvelopePlugin],
  registryUrl: 'https://registry.example.com',
})
 
// Look up a user's profile
const profile = await sdk.profiles.getProfile(otherPubHex)
console.log(profile.name)
 
// List my enclaves
const myEnclaves = await sdk.registry.lookupByOwner(identity.publicKeyHex, 'personal')
console.log(myEnclaves.length, 'Personal enclaves')
 
// Subscribe to events
sdk.subscriber.add(myEnclaves[0].enclaveId)
sdk.subscriber.on('event', (event, enclaveId) => {
  console.log(`Event from ${enclaveId}:`, event.type, event.content)
})

See also