@universal-trust/sdk
v0.1.0
Published
SDK for Universal Trust — Agent identity & trust verification on LUKSO
Maintainers
Readme
@universal-trust/sdk
TypeScript SDK for Universal Trust — on-chain agent identity & trust verification on LUKSO.
Installation
npm install @universal-trust/sdkRequires 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 + feedbackBonusA 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 BaseEOAs 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.tsAgent-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.tsCustom 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.tsTrust 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:0x16505FeC789F4553Ea88d812711A0E913D926ADDgetAgentTrustReadinessSummary() 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 capabilitiesThe 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:customOpenClaw 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:guardUse 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:manifestOr 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,000hasEndorsed(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:checkThat 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
