@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/servicesDepends 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) → voidPublish or update an identity's profile.
.clearCache()
profiles.clearCache() → voidClear 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) → voidSend 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 IDAdd 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) → voidClose 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
) → voidRegister 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:
| Parameter | Type | Description |
|---|---|---|
appId | string | App identifier |
identity | Object | Identity with private key and pubkey hex |
adapter | Object | Transport adapter (NetworkAdapter, etc.) |
plugins | Object[] | Confidentiality plugins |
registryUrl | string | Registry endpoint |
nodeUrl | string | Node 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
@enc-protocol/core— protocol primitives@enc-protocol/app-sdk-base— app SDK base classes@enc-protocol/plugin-runtime— plugin interfaces- App SDKs — per-app service bindings