@app_/registry-client

HTTP client for Atlas Registry services — data catalogs that store and serve envelopes. Handles authentication, envelope CRUD, blob uploads, catalog discovery, and FairShares transactions.

Creating a client

The client requires callback functions that provide the current session's public key, proofs, and delegated private key. These are used to automatically construct authentication headers on every request.

import { createRegistryClient } from '@app_/registry-client';

const registry = createRegistryClient({
  getPublicKey: () => session.publicKey,
  getProofs: () => session.proofs,
  getDelegatedPrivateKey: () => session.delegatedPrivateKey,
  autoBuyFairShares: 10,  // optional: auto-buy query access
});
// Every request automatically includes authentication headers:
// atlas-identity:  <publicKey>
// atlas-proofs:    <JSON array of PoW/Permit proofs>
// atlas-signature: t=<timestamp>; s=<HMAC signature>

Envelopes

Envelopes are the primary data unit — signed, content-addressed containers wrapping Schema.org-typed data. The client supports fetching, publishing, and multi-registry operations.

// Fetch envelopes with optional query filters
const envelopes = await registry.getEnvelopes(
  'https://registry.example',
  { '@type': 'Article', limit: 20 },
);

// Get a single envelope by hash
const envelope = await registry.getEnvelope(
  'https://registry.example',
  'a1b2c3...hash',
);

// Fetch from multiple registries (deduplicates URLs)
const results = await registry.getEnvelopesByRegistry(
  ['https://reg1.example', 'https://reg2.example'],
  { '@type': 'Person' },
);

// Get from the first registry that has it
const found = await registry.getEnvelopeFromAnyRegistry(
  ['https://reg1.example', 'https://reg2.example'],
  'a1b2c3...hash',
);

// Create (publish) envelopes
const result = await registry.createEnvelopes(
  ['https://reg1.example'],
  [signedEnvelope],
  ['envelopeHash'],
);
// Returns: { ok, hashes[], deliveryResults: { [url]: { ok, hashes[] } } }

Blob uploads

Upload files in 5MB chunks with progress tracking.

// Upload a file in 5MB chunks with progress callback
const result = await registry.uploadBlobChunked(
  'https://registry.example',
  file,  // File object
  (progress) => console.log(progress + '% uploaded'),
);

Discovery & catalogs

Registries publish DataCatalog envelopes describing their content and capabilities. The client provides methods to discover registries, verify their identity, and search across catalogs.

// Fetch connected data catalogs
const catalogs = await registry.getConnectedCatalogs('https://registry.example');

// Fetch a registry's own DataCatalog envelope
const catalog = await registry.fetchCatalogEnvelope('https://registry.example');

// Fetch and verify a registry's identity (public key)
const { publicKey, hash } = await registry.fetchRegistryIdentity('https://registry.example');

// Search across catalogs by type
const results = await registry.guidedSearch(
  'https://guide.example',  // guide registry URL
  'Article',                 // Schema.org type
  { name: 'search term' },  // optional query
  { limit: 10 },            // optional window
);

// Get registries with shelter (hosting) available
const shelters = await registry.getAvailableShelters('https://guide.example');

Query access & FairShares

Querying a registry may require spending FairShares. Use autoBuyFairShares in the client config for automatic purchasing, or buy manually.

// Buy query access with FairShares
await registry.buyQueryAccess(
  'https://registry.example',
  'sellerPublicKeyHash',
  { amount: 10 },
);

Counts

// Get envelope counts grouped by type
const counts = await registry.getCounts<{ type: string; count: number }>(
  'https://registry.example',
  { authorHash: 'abc123...' },
);

Setup & administration

// Check registry setup status
const status = await registry.getSetupStatus('https://registry.example');
// { isSetupComplete, isRegistryLocked, isOperatorAuthorized, canSetupOperator, canRecoverOperator }

// Connect as operator
const result = await registry.connectOperator(
  'https://registry.example',
  'operatorPublicKeyHash',
  true,  // allowRecovery
);

// Generic authenticated requests
const data = await registry.get<MyType>('https://registry.example', '/custom/path');
const response = await registry.post<MyType>('https://registry.example', '/custom/path', body);

API methods

Method Description
getEnvelopes(url, query?)Fetch envelopes with filters
getEnvelope(url, hash)Get single envelope by hash
getEnvelopesByRegistry(urls, query?)Fetch from multiple registries
getEnvelopeFromAnyRegistry(urls, hash)Get from first available
createEnvelopes(urls, envelopes, hashes)Publish envelopes
uploadBlobChunked(url, file, onProgress?)Upload file in 5MB chunks
getCounts(url, params?)Envelope counts by type
buyQueryAccess(url, sellerHash, config)Buy access with FairShares
getConnectedCatalogs(url)List connected DataCatalogs
fetchRegistryIdentity(url)Get and verify registry public key
fetchCatalogEnvelope(url)Get registry's own DataCatalog
guidedSearch(url, type, query?, window?)Search across catalogs
getAvailableShelters(url)Find registries offering hosting
getSetupStatus(url)Check registry setup state
connectOperator(url, hash, recovery?)Connect as operator
get(url, path)Authenticated GET
post(url, path, body)Authenticated POST