npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@universal-trust/sdk

v0.1.0

Published

SDK for Universal Trust — Agent identity & trust verification on LUKSO

Readme

@universal-trust/sdk

TypeScript SDK for Universal Trust — on-chain agent identity & trust verification on LUKSO.

npm version Tests


Installation

npm install @universal-trust/sdk

Requires Node.js ≥ 18.


Quick Start

import { AgentTrust } from '@universal-trust/sdk';

// Zero config — uses LUKSO mainnet + deployed contracts
const trust = new AgentTrust({});

// Verify an agent
const result = await trust.verify('0x293E96ebbf264ed7715cff2b67850517De70232a');
console.log(result);
// {
//   registered: true,
//   active: true,
//   isUniversalProfile: true,
//   reputation: 100,
//   endorsements: 1,
//   trustScore: 110,
//   name: "LUKSO Agent",
//   chain: { key: "lukso-mainnet", chainId: 42, ... },
//   account: { address: "0x293E...", isUniversalProfile: true }
// }

Multi-chain verification (anti-gaming composite)

import { MultiChainAgentTrust } from '@universal-trust/sdk';

const trust = new MultiChainAgentTrust({
  chains: ['lukso-mainnet', 'ethereum-mainnet', 'base-mainnet'],
});

const profile = await trust.getMultiChainProfile('0x293E96ebbf264ed7715cff2b67850517De70232a');
console.log(profile.composite.total);            // anti-gaming composite
console.log(profile.composite.rationale);        // explainer text
console.log(profile.earnedChains.map((p) => p.chain));

Composite formula (lives in computeMultiChainCompositeScore):

base             = max(trustScore) across "earned" chains
crossChainBonus  = min(50, round(sqrt(earnedChainCount) * 10))     // diminishing
activityBonus    = sum(max(0, reputation - 100)) across earned, capped at 200
endorsementBonus = sum(endorsements) * 5 across earned, capped at 100
feedbackBonus    = min(75, uniqueFeedbackGiversAcrossChains * 3)
total            = base + crossChainBonus + activityBonus + endorsementBonus + feedbackBonus

A chain only contributes if it has earned signal: an endorsement, reputation above the default 100, or an ERC-8004 identity token. Empty registrations count as 0, so agents cannot inflate the score by registering on every chain.

EOA & smart-contract wallet support

register() and endorse() accept either a private key (Node-side) or an ExternalSigner — an { address, sendTransaction(tx) } object that submits the populated transaction however your wallet prefers. The SDK never sees the secret key.

For multichain agents, prefer registerAgent(). It uses Universal Trust when AgentIdentityRegistry is deployed on the selected chain and falls back to the official ERC-8004 IdentityRegistry when Universal Trust is not deployed yet.

import { AgentTrust, type ExternalSigner } from '@universal-trust/sdk';

const trust = new AgentTrust({});

// Option 1 — return raw transaction data and submit elsewhere
const tx = trust.buildRegisterTx('My Agent', 'What it does', 'ipfs://...');
const hash = await window.ethereum.request({
  method: 'eth_sendTransaction',
  params: [{ ...tx, from: userAddress }],
});

// Option 2 — pass an ExternalSigner
const signer: ExternalSigner = {
  address: userAddress,
  async sendTransaction(populated) {
    const hash = await window.ethereum.request({
      method: 'eth_sendTransaction',
      params: [{ ...populated, from: userAddress }],
    });
    return { transactionHash: hash };
  },
};
await trust.register('My Agent', 'What it does', signer, 'ipfs://...');

// Chain-aware registration: Universal Trust when available, ERC-8004 otherwise.
const baseTrust = new AgentTrust({ chain: 'base-mainnet' });
const result = await baseTrust.registerAgent(
  {
    name: 'My Agent',
    description: 'What it does',
    metadataURI: 'ipfs://universal-trust-metadata',
    agentURI: 'ipfs://erc8004-agent-metadata',
  },
  signer,
);
console.log(result.registry); // "erc8004" until Universal Trust is deployed on Base

EOAs can register on every chain. Universal Trust endorsements default to the LUKSO policy: the endorser must be a Universal Profile/ERC725-compatible contract account. For EOA-first chains deployed with ALLOW_EOA_ENDORSERS=true, pass allowEoaEndorsers: true in the SDK chain config so agent runtimes know EOA wallets may call endorse() directly.

Cross-chain reputation feedback (ERC-8004 ReputationRegistry)

An EOA on any supported chain can publish on-chain reputation feedback about any registered agent. The composite picks it up automatically and applies anti-gaming caps:

import { AgentTrust } from '@universal-trust/sdk';

const trust = new AgentTrust({ chain: 'ethereum-mainnet' });

// Submit feedback from a browser EOA
await trust.giveFeedback(42n, 85, signer, {
  tag1: 1,
  tag2: 'task-quality',
  fileuri: 'ipfs://Qm…',
});

// Or build the tx for any wallet
const tx = trust.buildGiveFeedbackTx(42n, 85, { tag1: 1 });

// Read summary
const { count, averageScore, totalScore, clients } = await trust.getFeedbackSummary(42n);

Composite rule: feedbackBonus = min(75, uniqueFeedbackGiversAcrossChains × 3). Replaying the same signer across N chains counts as one unique giver, so a sybil cannot multiply the bonus by spraying feedback everywhere.

Verify end-to-end:

npx tsx examples/cross-chain-feedback.ts

Agent-to-Agent Trust

The core use case: one AI agent verifying another's identity before interacting.

import { AgentTrust } from '@universal-trust/sdk';

const trust = new AgentTrust({});
const MIN_TRUST = 100;

async function handleAgentRequest(callerAddress: string, request: any) {
  const v = await trust.verify(callerAddress);

  if (!v.registered) throw new Error('Unknown agent — not in registry');
  if (!v.active)     throw new Error('Agent deactivated');
  if (v.trustScore < MIN_TRUST) throw new Error(`Trust too low: ${v.trustScore}`);

  // Verified — safe to proceed
  console.log(`Accepted request from ${v.name} (trust: ${v.trustScore})`);
  return processRequest(request);
}

No API keys. No OAuth tokens. One on-chain call resolves identity.

Run the full example:

npx tsx examples/agent-to-agent.ts

Custom or non-LUKSO networks:

Use getCapabilities() before calling Universal Trust APIs on non-default chains. Base and Ethereum expose official ERC-8004 registries, but Universal Trust contracts are not deployed there yet.

npx tsx examples/custom-network-skills.ts

Trust Verification Flow

Your App / Agent
      │
      │  trust.verify(address)
      ▼
┌─────────────────────────┐
│   AgentTrust SDK        │
│   (validates address)   │
└────────────┬────────────┘
             │  eth_call via Web3.js
             │  (with auto-retry + backoff)
             ▼
┌─────────────────────────────────────────────────────┐
│   AgentIdentityRegistry (LUKSO Mainnet)              │
│   0x16505FeC789F4553Ea88d812711A0E913D926ADD        │
│                                                       │
│   verify(address) returns:                           │
│     registered    bool                               │
│     active        bool                               │
│     isUP          bool   ← ERC165 UP check           │
│     reputation    uint256                            │
│     endorsements  uint256                            │
│     trustScore    uint256 = rep + (endorse × 10)     │
│     name          string                             │
└─────────────────────────────────────────────────────┘
             │
             │  (optional: getProfile also queries)
             ▼
┌─────────────────────────────────────────────────────┐
│   AgentSkillsRegistry (LUKSO Mainnet)                │
│   0x64B3AeCE25B73ecF3b9d53dA84948a9dE987F4F6        │
│   getSkillKeys() → getSkill() for each key           │
└─────────────────────────────────────────────────────┘

Configuration

const trust = new AgentTrust({
  // Chain preset (default: 'lukso-mainnet')
  // Also available as official ERC-8004 targets: 'ethereum-mainnet', 'base-mainnet'
  chain: 'lukso-mainnet',

  // LUKSO RPC endpoint (default: https://rpc.mainnet.lukso.network)
  rpcUrl: 'https://rpc.mainnet.lukso.network',

  // Contract addresses — already set to deployed mainnet contracts
  identityRegistryAddress: '0x16505FeC789F4553Ea88d812711A0E913D926ADD',
  skillsRegistryAddress: '0x64B3AeCE25B73ecF3b9d53dA84948a9dE987F4F6',

  // RPC retry config
  maxRetries: 3,       // default: 3
  retryDelayMs: 1000,  // default: 1000ms (exponential backoff)
});

Custom chain deployments are supported by passing full chain metadata:

const trust = new AgentTrust({
  chain: {
    key: 'my-agent-chain',
    name: 'My Agent Chain',
    chainId: 12345,
    rpcUrl: 'https://rpc.example',
    identityRegistryAddress: '0x1111111111111111111111111111111111111111',
    skillsRegistryAddress: '0x2222222222222222222222222222222222222222',
    nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
    blockExplorerUrl: 'https://explorer.example',
  },
});

console.log(trust.getChain());
console.log(trust.getCapabilities().ready);

The chain metadata also exposes official ERC-8004 registries separately from Universal Trust deployments. This lets callers discover Ethereum/Base agents without treating the ERC-8004 IdentityRegistry as Universal Trust's AgentIdentityRegistry.

const base = new AgentTrust({ chain: 'base-mainnet' }).getChain();
console.log(base.officialErc8004?.agentRegistry);
// eip155:8453:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432

await new AgentTrust({ chain: 'base-mainnet' }).verify('0x0000000000000000000000000000000000000001');
// throws AgentTrustError { code: 'UNSUPPORTED_NETWORK_FEATURE' }

API Reference

verify(address): Promise<VerifyResult>

Core verification call. Returns a full trust summary for an agent address.

const result = await trust.verify('0x293E96ebbf264ed7715cff2b67850517De70232a');

// VerifyResult shape:
// {
//   registered: boolean        — is this agent in the registry?
//   active: boolean            — is the agent currently active?
//   isUniversalProfile: boolean — is this a LUKSO UP (ERC165)?
//   reputation: number         — reputation score (0–10,000)
//   endorsements: number       — number of peer endorsements
//   trustScore: number         — rep + (endorsements × 10)
//   name: string               — agent display name
//   chain: ChainContext         — resolved chain metadata
//   account: AccountContext     — verified account metadata
// }

verifyBatch(addresses): Promise<Map<string, VerifyResult>>

Verify multiple agents concurrently. Returns a Map from address to result. Failed RPC lookups on a configured deployment return a default unregistered result. Missing deployments, such as Base/Ethereum today, throw UNSUPPORTED_NETWORK_FEATURE instead of pretending the chain has a working Universal Trust registry.

const agents = [
  '0x7315D3fab45468Ca552A3d3eeaF5b5b909987B7b',
  '0x293E96ebbf264ed7715cff2b67850517De70232a',
];

const results = await trust.verifyBatch(agents);

for (const [addr, result] of results) {
  if (result.registered && result.trustScore >= 100) {
    console.log(`${addr}: trusted (score=${result.trustScore})`);
  }
}

getProfile(address): Promise<AgentProfile>

Full agent profile including skills and endorsers. Makes multiple RPC calls (identity + skills + endorsers). Throws CONTRACT_REVERT if the agent is not registered — use isRegistered() or verify() first.

const profile = await trust.getProfile('0x293E96ebbf264ed7715cff2b67850517De70232a');

// AgentProfile shape:
// {
//   address: string
//   name: string
//   description: string
//   metadataURI: string
//   reputation: number
//   endorsementCount: number
//   registeredAt: number       — Unix timestamp
//   lastActiveAt: number       — Unix timestamp
//   isActive: boolean
//   isUniversalProfile: boolean
//   skills: SkillInfo[]        — from AgentSkillsRegistry
//   endorsers: string[]        — addresses that endorsed this agent
// }

isRegistered(address): Promise<boolean>

Quick check if an agent is registered.

if (await trust.isRegistered('0xABC...')) {
  // agent exists in registry
}

getChain(): ChainContext

Return the resolved chain metadata for this SDK instance. Zero config remains backwards-compatible and resolves to LUKSO mainnet. chain and network selectors both expose chain-qualified ERC-8004 registry IDs when the selected profile includes them.

const trust = new AgentTrust();
const chain = trust.getChain();
// { key: 'lukso-mainnet', name: 'LUKSO Mainnet', chainId: 42, ... }
console.log(chain.officialErc8004?.identityRegistryId);

validateDeployment(): DeploymentValidationResult

Validate whether the resolved chain has configured registry deployments. This is useful for presets such as Ethereum or Base mainnet where chain metadata exists but Universal Trust contracts may not be deployed yet.

const trust = new AgentTrust({ chain: 'base-mainnet' });
const deployment = trust.validateDeployment();

if (!deployment.valid) {
  console.log('Missing:', deployment.missing);
}

getCapabilities(): AgentTrustCapabilities

Return an agent-friendly capability summary for the selected chain. Use this in OpenClaw skills and other agent runtimes so they can branch cleanly between Universal Trust deployments, identity-only deployments, and chains that only publish official ERC-8004 registry metadata.

const trust = new AgentTrust({ chain: 'base-mainnet' });
const caps = trust.getCapabilities();

if (caps.identityRegistry.canVerify) {
  await trust.verify(agentAddress);
}

if (caps.skillsRegistry.canRead) {
  await trust.getSkills(agentAddress);
}

console.log(caps.officialErc8004.identityRegistryId);
console.log(caps.officialErc8004.canRegisterIdentity);
console.log(caps.officialErc8004.canGiveFeedback);
console.log(caps.identityRegistry.requiresUniversalProfileEndorser);

For callers that only need metadata and do not want to instantiate the SDK:

import {
  getAgentTrustCapabilities,
  getAgentTrustRegistryIds,
  getAgentTrustReadinessSummary,
} from '@universal-trust/sdk';

const caps = getAgentTrustCapabilities({ chain: 'base-mainnet' });
console.log(caps.ready, caps.missing, caps.officialErc8004.agentRegistry);

const guard = getAgentTrustReadinessSummary({ chain: 'base-mainnet' });
console.log(guard.safeCalls.verifyIdentity, guard.nextAction);
console.log(guard.safeCalls.registerOfficialErc8004);
console.log(guard.safeCalls.endorseUniversalTrustWithEoa);
console.log(guard.registryIds.chain.caip2, guard.registryIds.officialErc8004.agentRegistry);

const ids = getAgentTrustRegistryIds({ network: 'lukso-mainnet' });
console.log(ids.universalTrust.identityRegistryId);
// eip155:42:0x16505FeC789F4553Ea88d812711A0E913D926ADD

getAgentTrustReadinessSummary() returns the same JSON shape used by the OpenClaw runtime guard, so AgentSkills can branch without copying example code. It also embeds registryIds, giving agents CAIP-style IDs for manifests, logs, and discovery without a second helper call. getAgentTrustRegistryIds() returns CAIP-style registry IDs for manifests, discovery files, and chain-aware agent logs without making RPC calls.

Instance users can call the same helper on a configured SDK client:

const trust = new AgentTrust({ network: 'lukso-mainnet' });
const ids = trust.getRegistryIds();

console.log(ids.chain.caip2);
console.log(ids.universalTrust.identityRegistryId);
console.log(ids.officialErc8004.agentRegistry);

To inspect every built-in chain preset from an agent shell without making RPC calls or sending transactions:

npm run capabilities

The report prints whether each chain has Universal Trust identity reads, skill reads, and official ERC-8004 metadata configured. The package script uses the local tsx dev dependency so agents do not need to remember the example path.

For OpenClaw AgentSkills or other agent runtimes that already have their own chain list, build a custom-only report. This keeps built-in presets out of the output and gives agents a simple JSON object for branching:

import { getAgentTrustCapabilityReport } from '@universal-trust/sdk';

const rows = getAgentTrustCapabilityReport({
  includeBuiltInChains: false,
  configs: [
    {
      network: {
        key: 'agent-testnet',
        name: 'Agent Testnet',
        chainId: 4242,
        rpcUrl: 'https://rpc.agent-testnet.example',
        identityRegistryAddress: '0x1111111111111111111111111111111111111111',
        skillsRegistryAddress: '0x2222222222222222222222222222222222222222',
      },
    },
  ],
});

const [agentChain] = rows;
if (agentChain.universalTrustIdentity) {
  // Safe to call verify(), isRegistered(), and trust score reads on this chain.
}
if (agentChain.universalTrustSkills) {
  // Safe to call getSkills() and profile reads that include skills.
}

Run the custom-only JSON example:

npm run capabilities:custom

OpenClaw AgentSkills can run a smaller guard that prints only the selected runtime chain and the safe feature booleans. It performs no RPC calls and sends no transactions:

npm run agent:skill:guard
UNIVERSAL_TRUST_CHAIN=base-mainnet npm run agent:skill:guard
UNIVERSAL_TRUST_NETWORK_JSON='{"key":"agent-testnet","name":"Agent Testnet","chainId":4242,"rpcUrl":"https://rpc.example","identityRegistryAddress":"0x1111111111111111111111111111111111111111"}' npm run agent:skill:guard

Use safeCalls.verifyIdentity before verify() or isRegistered(), and use safeCalls.readSkills before getSkills() or profile reads that include skill metadata. Use safeCalls.endorseUniversalTrustWithEoa before allowing an EOA agent to call endorse(); if it is false, use a UP/ERC725-compatible signer or ERC-8004 feedback instead. If a registry flag is false, skip that optional path instead of probing a missing registry. Use registryIds.chain.caip2 and the nested registry IDs when writing OpenClaw skill manifests or chain-aware logs.

To generate a portable OpenClaw AgentSkill manifest snippet from the same zero-RPC gates and registry IDs:

npm run agent:skill:manifest
UNIVERSAL_TRUST_CHAIN=base-mainnet npm run agent:skill:manifest
UNIVERSAL_TRUST_SKILL_NAME=my-agent-skill UNIVERSAL_TRUST_SKILL_VERSION=1.2.3 npm run agent:skill:manifest

Or call the manifest helper directly:

import { getOpenClawAgentSkillManifest } from '@universal-trust/sdk';

const manifest = getOpenClawAgentSkillManifest(
  { chain: 'base-mainnet' },
  { name: 'my-agent-skill', version: '1.2.3' },
);

if (!manifest.universalTrust.safeCalls.verifyIdentity) {
  // Skip Universal Trust verify/isRegistered/trust-score reads on this chain.
}

console.log(manifest.universalTrust.registryIds.chain.caip2);

getTrustScore(address): Promise<number>

Get the composite trust score directly. Reverts if the agent is not registered — use verify() for safe lookups.

const score = await trust.getTrustScore('0x293E...');
// score = reputation + (endorsementCount * 10), capped at 10,000

hasEndorsed(endorser, endorsed): Promise<boolean>

Check if one agent has endorsed another.

const endorsed = await trust.hasEndorsed(
  '0x7315D3fab45468Ca552A3d3eeaF5b5b909987B7b',  // endorser
  '0x293E96ebbf264ed7715cff2b67850517De70232a',  // endorsed
);

getEndorsers(address): Promise<string[]>

Get all addresses that have endorsed an agent.

const endorsers = await trust.getEndorsers('0x293E...');
console.log(`${endorsers.length} endorsers`);

getEndorsement(endorser, endorsed): Promise<EndorsementInfo>

Get details of a specific endorsement between two agents. Returns exists: false if no endorsement found.

const endorsement = await trust.getEndorsement(
  '0x7315D3fab45468Ca552A3d3eeaF5b5b909987B7b',  // endorser
  '0x293E96ebbf264ed7715cff2b67850517De70232a',  // endorsed
);

if (endorsement.exists) {
  console.log(`Endorsed at ${new Date(endorsement.timestamp * 1000).toISOString()}`);
  console.log(`Reason: "${endorsement.reason}"`);
}

// EndorsementInfo shape:
// {
//   endorser: string
//   endorsed: string
//   timestamp: number    — Unix timestamp (0 if not found)
//   reason: string       — endorsement reason text
//   exists: boolean      — whether this endorsement exists
// }

getEndorsementCount(address): Promise<number>

Get the number of endorsements an agent has received.

const count = await trust.getEndorsementCount('0x293E...');
console.log(`${count} endorsements received`);

getAgentCount(): Promise<number>

Total number of registered agents in the registry.

const count = await trust.getAgentCount();
console.log(`${count} agents registered`);

getAgentsByPage(offset, limit): Promise<string[]>

Paginate through the agent registry.

// Get first 10 agents
const page1 = await trust.getAgentsByPage(0, 10);

// Get next 10
const page2 = await trust.getAgentsByPage(10, 10);

getSkills(address): Promise<SkillInfo[]>

Get all skills for an agent from the AgentSkillsRegistry. On custom or non-LUKSO deployments, guard this optional API with supportsSkillsRegistry() first.

if (!trust.supportsSkillsRegistry()) {
  console.log('Skill registry not configured for this chain');
  return;
}

const skills = await trust.getSkills('0x293E...');
for (const skill of skills) {
  console.log(`${skill.name} v${skill.version} (key: ${skill.key})`);
}

// SkillInfo shape:
// {
//   key: string      — bytes32 skill identifier
//   name: string
//   version: number
//   updatedAt: number — Unix timestamp
// }

getSkillContent(address, skillKey): Promise<{name, content, version}>

Get the full content of a specific skill (includes the skill content string).

const skill = await trust.getSkillContent('0x293E...', '0xskillkey...');
console.log(skill.content);

endorse(endorsed, privateKey, reason?): Promise<{transactionHash}>

Endorse another agent. Both agents must be registered and active. Never hardcode private keys.

const receipt = await trust.endorse(
  '0x293E96ebbf264ed7715cff2b67850517De70232a',  // agent to endorse
  process.env.PRIVATE_KEY!,                        // your private key
  'Reliable and accurate agent',                   // optional reason
);
console.log('tx:', receipt.transactionHash);

register(name, description, privateKey, metadataURI?): Promise<{transactionHash, agentAddress}>

Register a new agent. The signer's address becomes the agent identity.

const receipt = await trust.register(
  'My AI Agent',
  'Specializes in DeFi arbitrage on LUKSO',
  process.env.PRIVATE_KEY!,
  'ipfs://QmYourMetadata',   // optional
);
console.log('Registered at:', receipt.agentAddress);
console.log('tx:', receipt.transactionHash);

getAgentsByReputation(minReputation, pageSize?): Promise<Array>

Discover agents with reputation at or above a threshold. Returns agents sorted by reputation descending.

const topAgents = await trust.getAgentsByReputation(200);
for (const agent of topAgents) {
  console.log(`${agent.name}: rep=${agent.reputation}, trust=${agent.trustScore}`);
}

// Each result: { address, name, reputation, trustScore, active }

isUniversalProfile(address): Promise<boolean>

Check if an address is a LUKSO Universal Profile using ERC165 interface checks for ERC725X + ERC725Y.

const isUP = await trust.isUniversalProfile('0x293E...');

isReputationUpdater(address): Promise<boolean>

Check if an address is authorized to update agent reputation scores.

const canUpdate = await trust.isReputationUpdater('0x7315...');

Error Handling

All methods throw AgentTrustError with a typed code for programmatic handling:

import { AgentTrust, AgentTrustError, AgentTrustErrorCode } from '@universal-trust/sdk';

try {
  const result = await trust.verify('0xinvalidaddress');
} catch (error) {
  if (error instanceof AgentTrustError) {
    switch (error.code) {
      case AgentTrustErrorCode.INVALID_ADDRESS:
        console.error('Bad address format:', error.message);
        break;
      case AgentTrustErrorCode.RPC_ERROR:
        console.error('Network failed after retries:', error.message);
        break;
      case AgentTrustErrorCode.CONTRACT_REVERT:
        console.error('Contract reverted:', error.message);
        break;
      case AgentTrustErrorCode.NOT_REGISTERED:
        console.error('Agent not found in registry');
        break;
      case AgentTrustErrorCode.TRANSACTION_FAILED:
        console.error('Transaction failed:', error.message);
        break;
    }
  }
}

Error Codes

| Code | When | |------|------| | INVALID_ADDRESS | Address fails 0x + 40 hex char check | | RPC_ERROR | Network/timeout failure after all retries | | CONTRACT_REVERT | On-chain execution revert (deterministic — not retried) | | TRANSACTION_FAILED | endorse() or register() tx failed | | NOT_REGISTERED | Agent lookup for unregistered address | | UNSUPPORTED_NETWORK_FEATURE | Selected chain does not have the requested Universal Trust contract deployed/configured | | INVALID_INPUT | Bad parameter (empty name, negative offset, etc.) |

Retry Behavior

RPC calls automatically retry with exponential backoff:

  • Attempt 1 → fail → wait 1s
  • Attempt 2 → fail → wait 2s
  • Attempt 3 → fail → wait 4s
  • Attempt 4 → throw RPC_ERROR

Contract reverts are not retried (they're deterministic).


Chain Presets

| Key | Chain ID | RPC | Deployment | |-----|----------|-----|------------| | lukso-mainnet | 42 | https://rpc.mainnet.lukso.network | Universal Trust deployed; official ERC-8004 Identity eip155:42:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432, Reputation eip155:42:0x8004BAa17C55a88189AE136b182e5fdA19dE9b63 | | ethereum-mainnet | 1 | https://ethereum-rpc.publicnode.com | Official ERC-8004 Identity/Reputation registries configured; Universal Trust verify/register/trust graph/skills actions throw UNSUPPORTED_NETWORK_FEATURE until contracts are deployed | | base-mainnet | 8453 | https://mainnet.base.org | Official ERC-8004 Identity/Reputation registries configured; Universal Trust verify/register/trust graph/skills actions throw UNSUPPORTED_NETWORK_FEATURE until contracts are deployed |

The SDK also includes official ERC-8004-only presets for Polygon, Arbitrum, Optimism, Avalanche, BNB Smart Chain, Celo, Gnosis, Linea, Mantle, Scroll, and Taiko. These presets intentionally have no Universal Trust deployment configured until chain-specific Universal Trust contracts are deployed.


Package Hygiene

The published package is intentionally small and consumer-safe. package.json sets files to dist, while npm still includes the required README.md, license, and package metadata. Source, examples, scripts, node_modules, and coverage output must stay out of the package tarball.

Before publishing or checking a release candidate, run:

npm run pack:check

That command rebuilds dist and runs npm pack --dry-run --json, then fails if required consumer files are missing or dev-only paths would be packaged. The expected consumer entrypoints are:

| Entrypoint | Purpose | |------------|---------| | dist/index.mjs | ESM import target | | dist/index.js | CommonJS require target | | dist/index.d.ts | TypeScript declarations | | dist/index.d.mts | ESM declaration mirror |

import { AgentTrust, getAgentTrustCapabilityReport } from '@universal-trust/sdk';
import type { AgentTrustConfig, UniversalTrustNetworkConfig } from '@universal-trust/sdk';

TypeScript Types

import type {
  AgentTrustConfig,
  TrustChainKey,
  TrustNativeCurrency,
  TrustChainConfig,
  ChainContext,
  AccountContext,
  DeploymentValidationResult,
  VerifyResult,
  AgentProfile,
  SkillInfo,
  EndorsementInfo,
} from '@universal-trust/sdk';

License

MIT