Skip to content

Sender SDK

The @directory/client SDK handles the full resolution flow: DNS discovery, capability fetching, address resolution, Ed25519 verification, and route matching.

Install

Terminal window
npm install @directory/client

Basic Usage

import { DirectoryClient } from '@directory/client';
const client = new DirectoryClient();
const result = await client.resolve('alice@gmail.com', [
{ value_type: 'USDC', transfer_type: 'ethereum' },
{ value_type: 'USDC', transfer_type: 'base' },
]);
if (result.verification.valid && result.matchedRoutes.length > 0) {
const route = result.matchedRoutes[0];
console.log(`Send ${route.value_type} on ${route.transfer_type} to ${route.destination}`);
}

What the SDK Does

The resolve() call performs these steps automatically:

  1. Discover — DNS-over-HTTPS lookup for _drs._tcp.{domain} SRV and _drskey.{domain} TXT
  2. Capabilities — Fetch GET /.well-known/directory.json from the DRS
  3. Resolve — Send POST /resolve with the address
  4. Verify — Check the Ed25519 signature against the DNS-published key, check TTL
  5. Match — Filter the contract’s routes against the sender’s capabilities

Step-by-Step (Lower Level)

If you need more control, use the individual functions:

import {
discoverDrs,
fetchCapabilities,
resolveAddress,
verifyContract,
matchRoutes,
} from '@directory/client';
// 1. Find the DRS via DNS
const { baseUrl, publicKey } = await discoverDrs('gmail.com');
// 2. What does it accept?
const manifest = await fetchCapabilities(baseUrl);
// 3. Resolve the address
const contract = await resolveAddress(baseUrl, 'alice@gmail.com');
// 4. Verify the signature
const verification = await verifyContract(contract, publicKey);
if (!verification.valid) throw new Error(verification.reason);
// 5. Match against what you can send
const senderCapabilities = [
{ value_type: 'USDC', transfer_type: 'ethereum' },
];
const routes = matchRoutes(contract.routes, senderCapabilities);

Exchange Node Resolution

When the recipient’s DRS doesn’t accept what you can send, route through an exchange node:

const result = await client.resolve('alice@gmail.com', [
{ value_type: 'USDC', transfer_type: 'ethereum' },
], {
exchangeDomain: 'bridge.money',
pathwayTo: { value_type: 'USD', transfer_type: 'ach' },
});

Error Handling

import { DrsDiscoveryError, DrsResolveError } from '@directory/client';
try {
const result = await client.resolve('alice@unknown.com', capabilities);
} catch (err) {
if (err instanceof DrsDiscoveryError) {
// No DRS found for domain — no SRV record
}
if (err instanceof DrsResolveError) {
// DRS returned an error — check err.code and err.status
// e.g., ADDRESS_NOT_FOUND (404), INVALID_REQUEST (400)
}
}

Runtime Compatibility

The SDK works in:

  • Node.js 20+ — native Web Crypto API
  • Cloudflare Workers — native Web Crypto API
  • Modern browsers — native Web Crypto API

Zero external dependencies for cryptographic operations.