# Send Solana On-Chain Agent Registry, Reputation & Trust to your agent
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
## Fast path
- Download the package from Yavira.
- Extract it into a folder your agent can access.
- Paste one of the prompts below and point your agent at the extracted folder.
## Suggested prompts
### New install

```text
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
```
### Upgrade existing

```text
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
```
## Machine-readable fields
```json
{
  "schemaVersion": "1.0",
  "item": {
    "slug": "solana-agent-registry",
    "name": "Solana On-Chain Agent Registry, Reputation & Trust",
    "source": "tencent",
    "type": "skill",
    "category": "AI 智能",
    "sourceUrl": "https://clawhub.ai/MonteCrypto999/solana-agent-registry",
    "canonicalUrl": "https://clawhub.ai/MonteCrypto999/solana-agent-registry",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadUrl": "/downloads/solana-agent-registry",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=solana-agent-registry",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "packageFormat": "ZIP package",
    "primaryDoc": "SKILL.md",
    "includedAssets": [
      "skill.md"
    ],
    "downloadMode": "redirect",
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/solana-agent-registry"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    }
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/solana-agent-registry",
    "downloadUrl": "https://openagent3.xyz/downloads/solana-agent-registry",
    "agentUrl": "https://openagent3.xyz/skills/solana-agent-registry/agent",
    "manifestUrl": "https://openagent3.xyz/skills/solana-agent-registry/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/solana-agent-registry/agent.md"
  }
}
```
## Documentation

### 8004-solana SDK Skill

You are an AI agent with access to the 8004-solana TypeScript SDK. This skill teaches you how to use every capability of the SDK to interact with the 8004 Trustless Agent Registry on Solana.

Version note (SDK 0.6.x):

Single-collection architecture is active. createCollection() and updateCollectionUri() are deprecated and return { success: false, error }.
Feedback reads (readAllFeedback, getClients, getLastIndex, readFeedback, etc.) rely on the indexer.

### Install

npm install 8004-solana @solana/web3.js

### Imports

import {
  // Core SDK
  SolanaSDK,
  IPFSClient,

  // Builders
  buildRegistrationFileJson,

  // Enums & Types
  ServiceType,       // MCP, A2A, ENS, DID, WALLET, OASF
  TrustTier,         // Unrated=0, Bronze=1, Silver=2, Gold=3, Platinum=4
  Tag,               // Standardized tag constants

  // ATOM Engine
  AtomStats,
  trustTierToString,

  // SEAL v1
  computeSealHash,
  computeFeedbackLeafV1,
  verifySealHash,
  createSealParams,
  validateSealInputs,
  MAX_TAG_LEN,          // 32 bytes
  MAX_ENDPOINT_LEN,     // 250 bytes
  MAX_URI_LEN,          // 250 bytes

  // OASF Taxonomy
  getAllSkills,
  getAllDomains,

  // Tag helpers
  isKnownTag,
  getTagDescription,

  // Signing
  buildSignedPayload,
  verifySignedPayload,
  parseSignedPayload,
  normalizeSignData,
  createNonce,
  canonicalizeJson,

  // Value encoding
  encodeReputationValue,
  decodeToDecimalString,
  decodeToNumber,

  // Crypto utilities
  keccak256,
  sha256,
  sha256Sync,          // Node.js only

  // Hash-chain replay
  replayFeedbackChain,
  replayResponseChain,
  replayRevokeChain,

  // Indexer
  IndexerClient,

  // Endpoint crawler
  EndpointCrawler,

  // Error classes
  IndexerError,
  IndexerUnavailableError,
  IndexerTimeoutError,
  IndexerRateLimitError,
  UnsupportedRpcError,
  RpcNetworkError,
} from '8004-solana';

import { Keypair, PublicKey } from '@solana/web3.js';

### Read-only (no wallet needed)

const sdk = new SolanaSDK({ cluster: 'devnet' });

### With signer (for write operations)

const signer = Keypair.fromSecretKey(
  Uint8Array.from(JSON.parse(process.env.SOLANA_PRIVATE_KEY!))
);
const sdk = new SolanaSDK({ signer });

### With custom RPC (required for bulk queries)

const sdk = new SolanaSDK({
  rpcUrl: 'https://your-helius-rpc.helius.dev',
  signer,
});

### Full config

const sdk = new SolanaSDK({
  cluster: 'devnet',
  rpcUrl: 'https://...',
  signer: keypair,
  indexerUrl: 'https://xxx.supabase.co/rest/v1',
  indexerApiKey: process.env.INDEXER_API_KEY, // if your indexer requires an API key, keep it in env
  useIndexer: true,
  indexerFallback: true,
  forceOnChain: false,
});

### IPFS client

// Pinata (recommended)
const ipfsPinata = new IPFSClient({
  pinataEnabled: true,
  pinataJwt: process.env.PINATA_JWT!,
});

// Local node
const ipfsLocal = new IPFSClient({ url: 'http://localhost:5001' });

### Step 1: Build metadata

const metadata = buildRegistrationFileJson({
  name: 'My Agent',
  description: 'Autonomous trading agent',
  image: 'ipfs://QmImageCid...',
  services: [
    { type: ServiceType.MCP, value: 'https://my-agent.com/mcp' },
    { type: ServiceType.A2A, value: 'https://my-agent.com/a2a' },
  ],
  skills: ['advanced_reasoning_planning/strategic_planning'],
  domains: ['finance_and_business/finance'],
  x402Support: true,
});

### Step 2: Upload to IPFS

const cid = await ipfs.addJson(metadata);

### Step 3: Register on-chain

const result = await sdk.registerAgent(\`ipfs://${cid}\`);
// result.asset   -> PublicKey (agent NFT address)
// result.signature -> transaction signature
// ATOM stats are auto-initialized

### Step 4: Set operational wallet

const opWallet = Keypair.generate();
await sdk.setAgentWallet(result.asset, opWallet);

### Collection (v0.6.x: single-collection)

All agents register into the base collection automatically. createCollection() and updateCollectionUri() are deprecated and return { success: false }.

const baseCollection = await sdk.getBaseCollection();

### 3. Read Agent Data

// Load agent
const agent = await sdk.loadAgent(assetPubkey);
// agent.getOwnerPublicKey(), agent.getAgentWalletPublicKey(), agent.agent_uri, etc.

// Check existence
const exists = await sdk.agentExists(assetPubkey);

// Get owner
const owner = await sdk.getAgentOwner(assetPubkey);

// Check ownership
const isMine = await sdk.isAgentOwner(assetPubkey, myPubkey);

// On-chain metadata
const version = await sdk.getMetadata(assetPubkey, 'version');

### Bulk queries (requires premium RPC: Helius, QuickNode, Alchemy)

const allAgents = await sdk.getAllAgents();
const withFeedbacks = await sdk.getAllAgents({ includeFeedbacks: true });
const myAgents = await sdk.getAgentsByOwner(ownerPubkey);

### 4. Update Agent

// Update metadata URI
await sdk.setAgentUri(assetPubkey, collectionPubkey, \`ipfs://${newCid}\`);

// Set on-chain key-value metadata
await sdk.setMetadata(assetPubkey, 'version', '2.0.0');
// First call: ~0.00319 SOL (PDA rent). Updates: ~0.000005 SOL (tx fee only)

// Immutable metadata (permanent, cannot change or delete)
await sdk.setMetadata(assetPubkey, 'certification', 'audited-2026', true);

// Delete metadata (recovers rent)
await sdk.deleteMetadata(assetPubkey, 'version');

// Transfer ownership
await sdk.transferAgent(assetPubkey, collectionPubkey, newOwnerPubkey);

// Sync owner after external NFT transfer
await sdk.syncOwner(assetPubkey);

### Give feedback

// Decimal string auto-encodes: "99.77" -> { value: 9977n, valueDecimals: 2 }
await sdk.giveFeedback(assetPubkey, {
  value: '99.77',
  tag1: Tag.uptime,
  tag2: Tag.day,
  score: 95,                          // 0-100, optional
  endpoint: '/api/v1/generate',       // optional, max 250 bytes
  feedbackUri: \`ipfs://${feedbackCid}\`,
  feedbackFileHash,                   // optional, 32 bytes Buffer (links file to SEAL)
});

### GiveFeedbackParams reference

FieldTypeRequiredDescriptionvaluestring | number | bigintYesMetric value. Strings auto-encode decimals ("99.77" -> 9977n, 2)valueDecimalsnumber (0-6)NoOnly needed for raw int/bigint. Auto-detected for stringsscorenumber (0-100)NoExplicit ATOM score. If omitted, inferred from tag1tag1stringNoCategory tag (max 32 UTF-8 bytes)tag2stringNoPeriod/network tag (max 32 UTF-8 bytes)endpointstringNoEndpoint used (max 250 UTF-8 bytes)feedbackUristringYesURI to detailed feedback file (IPFS/HTTPS, max 250 bytes)feedbackFileHashBufferNoSHA-256 of feedback file content (32 bytes). Binds file to on-chain SEAL

### Value encoding patterns

// Percentage with 2 decimals: 99.75%
const feedbackExamples = [
{ value: '99.75', tag1: Tag.uptime },
// -> encoded: value=9975n, valueDecimals=2

// Milliseconds: 250ms
{ value: 250, tag1: Tag.responseTime, valueDecimals: 0 },

// Currency: $150.25
{ value: '150.25', tag1: Tag.revenues, tag2: Tag.week },

// Negative PnL: -$15.5
{ value: '-15.5', tag1: Tag.tradingYield, tag2: Tag.month },

// Binary check: reachable
{ value: 1, tag1: Tag.reachable, valueDecimals: 0, score: 100 },

// Quality rating (score only)
{ value: '85', tag1: Tag.starred, score: 85 },
];

### Score behavior

score: 95 -> explicit quality score, used directly by ATOM
score: undefined/null -> ATOM infers from tag1 if it's a known tag (uptime, successRate, starred)
Tags without auto-score (responseTime, revenues, etc.) require explicit score for ATOM impact

ATOM-enabled tags (auto-score from value): starred, uptime, successRate
Context-dependent tags (require explicit score): reachable, ownerVerified, responseTime, blocktimeFreshness, revenues, tradingYield

### Read feedback

// Single feedback
const fb = await sdk.readFeedback(assetPubkey, clientPubkey, 0);
// fb.value, fb.valueDecimals, fb.score, fb.tag1, fb.tag2, fb.sealHash

// All feedbacks for agent (indexer-backed)
const all = await sdk.readAllFeedback(assetPubkey);
const withRevoked = await sdk.readAllFeedback(assetPubkey, true);

// Last feedback index for a specific client (NOT a count)
const lastIndex = await sdk.getLastIndex(assetPubkey, clientPubkey);
const nextIndex = lastIndex + 1n; // if no feedback yet: lastIndex = -1n, nextIndex = 0n

// All clients who gave feedback (indexer-backed)
const clients = await sdk.getClients(assetPubkey);

// Via indexer (faster, no premium RPC needed)
const feedbacks = await sdk.getFeedbacksFromIndexer(assetPubkey, { limit: 50 });
const byEndpoint = await sdk.getFeedbacksByEndpoint('/api/generate');
const byTag = await sdk.getFeedbacksByTag('uptime');

### Revoke feedback

// Requires the sealHash from the original feedback
const fb = await sdk.readFeedback(assetPubkey, clientPubkey, 0);
await sdk.revokeFeedback(assetPubkey, 0, fb.sealHash!);

### Respond to feedback (as agent owner)

await sdk.appendResponse(
  assetPubkey,
  clientPubkey,
  0,                          // feedbackIndex
  fb.sealHash!,               // sealHash from the feedback
  \`ipfs://${responseCid}\`,    // response URI
);

// Read responses
const responses = await sdk.readResponses(assetPubkey, clientPubkey, 0);
const count = await sdk.getResponseCount(assetPubkey, clientPubkey, 0);

### Quick reputation summary

const summary = await sdk.getSummary(assetPubkey);
// summary.averageScore      -> 0-100
// summary.totalFeedbacks
// summary.positiveCount     -> score >= 50
// summary.negativeCount     -> score < 50

// With filters
const filtered = await sdk.getSummary(assetPubkey, 70);  // minScore=70
const byClient = await sdk.getSummary(assetPubkey, undefined, clientPubkey);

### ATOM stats (on-chain reputation engine)

const atom = await sdk.getAtomStats(assetPubkey);
if (atom) {
  atom.quality_score;             // 0-10000 (divide by 100 for percentage)
  atom.confidence;                // 0-10000
  atom.ema_score_fast;            // Fast EMA (reacts quickly)
  atom.ema_score_slow;            // Slow EMA (stable baseline)
  atom.ema_volatility;            // Score instability
  atom.diversity_ratio;           // 0-255 (unique caller diversity)
  atom.risk_score;                // 0-100
  atom.trust_tier;                // 0-4

  // Helper methods
  atom.getQualityPercent();       // quality_score / 100
  atom.getConfidencePercent();    // confidence / 100
  atom.getAverageScore();         // ema_score_slow / 100
  atom.estimateUniqueClients();   // HyperLogLog estimation
  atom.getTrustTier();            // TrustTier enum
}

### Trust tier

const tier = await sdk.getTrustTier(assetPubkey);
// TrustTier.Unrated   = 0
// TrustTier.Bronze    = 1
// TrustTier.Silver    = 2
// TrustTier.Gold      = 3
// TrustTier.Platinum  = 4

const name = trustTierToString(tier); // "Gold"

### Enriched summary (ATOM + raw feedback combined)

const enriched = await sdk.getEnrichedSummary(assetPubkey);
if (enriched) {
  enriched.trustTier;
  enriched.qualityScore;     // 0-10000
  enriched.confidence;       // 0-10000
  enriched.riskScore;        // 0-100
  enriched.diversityRatio;   // 0-255
  enriched.uniqueCallers;    // HLL estimate
  enriched.emaScoreFast;
  enriched.emaScoreSlow;
  enriched.volatility;
  enriched.totalFeedbacks;
  enriched.averageScore;     // 0-100
  enriched.positiveCount;
  enriched.negativeCount;
}

### Reputation from indexer

const rep = await sdk.getAgentReputationFromIndexer(assetPubkey);

### Sign data with agent wallet

const signedJson = sdk.sign(assetPubkey, {
  action: 'authorize',
  target: 'task-123',
  timestamp: Date.now(),
});
// Returns: JSON string of SignedPayloadV1

### Verify signature

// From JSON string
const isValidFromJson = await sdk.verify(signedJson, assetPubkey);

// From IPFS URI
const isValidFromIpfs = await sdk.verify('ipfs://QmPayload...', assetPubkey);

// From HTTPS URL
const isValidFromHttps = await sdk.verify('https://example.com/signed.json', assetPubkey);

// From file path
const isValidFromFile = await sdk.verify('./signed-payload.json', assetPubkey);

// With explicit public key
const isValidWithPubkey = await sdk.verify(signedJson, assetPubkey, walletPubkey);

### SignedPayloadV1 format

const exampleSignedPayload = {
  v: 1,
  alg: 'ed25519',
  asset: 'base58...',     // agent asset pubkey
  nonce: 'random-base58',
  issuedAt: 1234567890,   // unix seconds
  data: { action: 'authorize', target: 'task-123' }, // your payload
  sig: 'base58...',       // Ed25519 signature
};

### 8. Liveness Check

const defaultReport = await sdk.isItAlive(assetPubkey);
// report.status: 'live' | 'partially' | 'not_live'
// report.okCount, report.totalPinged, report.skippedCount
// report.liveServices[], report.deadServices[], report.skippedServices[]

// With options
const tunedReport = await sdk.isItAlive(assetPubkey, {
  timeoutMs: 10000,
  concurrency: 2,
  treatAuthAsAlive: true,           // 401/403 = alive
  includeTypes: [ServiceType.MCP],  // only check MCP endpoints
});

### 9. SEAL v1 (Feedback Authenticity)

SEAL provides client-side hash computation matching on-chain Keccak256. Required for revokeFeedback() and appendResponse().

// Build params (with optional feedbackFileHash)
const fileHash = await SolanaSDK.computeHash(JSON.stringify(feedbackFile));
const params = createSealParams(
  9977n,                        // value (i64)
  2,                            // decimals
  85,                           // score (or null)
  'uptime',                     // tag1
  'day',                        // tag2
  'https://api.example.com',    // endpoint (or null)
  'ipfs://QmFeedback...',       // feedbackUri
  fileHash,                     // feedbackFileHash (or null)
);

// Validate inputs before hashing (throws on invalid params)
validateSealInputs(params);

// Compute hash
const sealHash = computeSealHash(params);  // Buffer, 32 bytes (Keccak256)

// Verify
const valid = verifySealHash({ ...params, sealHash });  // true

// Compute feedback leaf (for hash-chain verification)
const leaf = computeFeedbackLeafV1(
  assetPubkey.toBuffer(),
  clientPubkey.toBuffer(),
  0n,           // feedbackIndex
  sealHash,
  12345n,       // slot
);

### Field size limits

FieldMax bytesConstanttag1, tag232 UTF-8MAX_TAG_LENendpoint250 UTF-8MAX_ENDPOINT_LENfeedbackUri250 UTF-8MAX_URI_LENfeedbackFileHash32 exact-

### Quick check (O(1))

const integrity = await sdk.verifyIntegrity(assetPubkey);
// integrity.valid        -> boolean
// integrity.status       -> 'valid' | 'syncing' | 'corrupted' | 'error'
// integrity.trustworthy  -> boolean
// integrity.totalLag     -> bigint (blocks behind)
// integrity.chains.feedback, .response, .revoke

### Deep verification (spot checks)

const deep = await sdk.verifyIntegrityDeep(assetPubkey, {
  spotChecks: 10,
  checkBoundaries: true,
  verifyContent: false,  // true = also verify IPFS content hashes (slow)
});
// deep.spotChecksPassed, deep.missingItems, deep.modifiedItems

### Full hash-chain replay

const full = await sdk.verifyIntegrityFull(assetPubkey, {
  onProgress: (chain, count, total) => {
    console.log(\`${chain}: ${count}/${total}\`);
  },
});

### Search agents (via indexer)

const results = await sdk.searchAgents({
  owner: 'base58...',
  collection: 'base58...',
  wallet: 'base58...',
  limit: 20,
  offset: 0,
});

### Leaderboard

const top = await sdk.getLeaderboard({
  minTier: 2,        // Silver+
  limit: 50,
  collection: 'base58...',
});

### Global stats

const global = await sdk.getGlobalStats();
// global.total_agents, total_feedbacks, platinum_agents, gold_agents, avg_quality

### Find agent by wallet

const agent = await sdk.getAgentByWallet(walletPubkey.toBase58());

### Endpoint crawler

const crawler = new EndpointCrawler(5000);
const mcp = await crawler.fetchMcpCapabilities('https://agent.com/mcp');
// mcp.mcpTools, mcp.mcpPrompts, mcp.mcpResources

const a2a = await crawler.fetchA2aCapabilities('https://agent.com');
// a2a.a2aSkills

### 12. SDK Introspection

// Chain identity (CAIP-2 format)
const chain = await sdk.chainId();       // 'solana-devnet'
const cluster = sdk.getCluster();         // 'devnet' | 'mainnet-beta' | 'testnet'

// Program IDs for all registries
const programs = sdk.getProgramIds();
// programs.identityRegistry   -> PublicKey
// programs.reputationRegistry -> PublicKey
// programs.validationRegistry -> PublicKey

// Registry addresses as strings (parity with agent0-ts)
const regs = sdk.registries();
// { IDENTITY: 'base58...', REPUTATION: 'base58...', VALIDATION: 'base58...' }

// RPC info
const rpcUrl = sdk.getRpcUrl();
const isDefaultRpc = sdk.isUsingDefaultDevnetRpc();
const canBulkQuery = sdk.supportsAdvancedQueries();
const readOnly = sdk.isReadOnly;

// Base collection (single-collection architecture in v0.6.x)
const base = await sdk.getBaseCollection();

// Advanced: access underlying clients
const solanaClient = sdk.getSolanaClient();
const feedbackMgr = sdk.getFeedbackManager();

### Category tags (tag1)

ConstantStringValue TypeATOM Auto-ScoreTag.starred'starred'0-100YesTag.uptime'uptime'percentageYesTag.successRate'successRate'percentageYesTag.reachable'reachable'0 or 1NoTag.ownerVerified'ownerVerified'0 or 1NoTag.responseTime'responseTime'msNoTag.blocktimeFreshness'blocktimeFreshness'blocksNoTag.revenues'revenues'currencyNoTag.tradingYield'tradingYield'percentageNo

### Period tags (tag2)

ConstantStringTag.day'day'Tag.week'week'Tag.month'month'Tag.year'year'

### x402 tags (tag1) - Client -> Agent

ConstantStringTag.x402ResourceDelivered'x402-resource-delivered'Tag.x402DeliveryFailed'x402-delivery-failed'Tag.x402DeliveryTimeout'x402-delivery-timeout'Tag.x402QualityIssue'x402-quality-issue'

### x402 tags (tag1) - Agent -> Client

ConstantStringTag.x402GoodPayer'x402-good-payer'Tag.x402PaymentFailed'x402-payment-failed'Tag.x402InsufficientFunds'x402-insufficient-funds'Tag.x402InvalidSignature'x402-invalid-signature'

### x402 network tags (tag2)

ConstantStringTag.x402Evm'exact-evm'Tag.x402Svm'exact-svm'

### Tag utilities

isKnownTag('uptime');              // true
isKnownTag('custom-metric');       // false
getTagDescription('successRate');   // 'Task completion success percentage'

Custom tags are fully supported - any string up to 32 UTF-8 bytes.

### 14. OASF Taxonomy

// List taxonomy slugs
const skills = getAllSkills();   // 136 skills
const domains = getAllDomains(); // 204 domains

### 15. Hash Utilities

// SHA-256 (async, browser-compatible via WebCrypto)
const hash = await SolanaSDK.computeHash('My feedback content');
const bufHash = await SolanaSDK.computeHash(Buffer.from(jsonData));
// Returns: Buffer (32 bytes)

// URI hash (zeros for IPFS/Arweave since CID is already content-addressable)
const uriHash = await SolanaSDK.computeUriHash('https://example.com/data.json');
// -> SHA-256 of the URI string
const ipfsHash = await SolanaSDK.computeUriHash('ipfs://Qm...');
// -> Buffer.alloc(32) (zeros)

// Keccak-256 (synchronous, used by SEAL v1)
import { keccak256 } from '8004-solana';
const k = keccak256(Buffer.from('data'));

// SHA-256 sync (CJS context only — uses require('crypto'), throws in pure ESM or browser)
import { sha256Sync } from '8004-solana';
const s = sha256Sync('data');  // Uint8Array (32 bytes)

### 16. Value Encoding

import {
  encodeReputationValue,
  decodeToDecimalString,
  decodeToNumber,
} from '8004-solana';

// Encode: decimal string -> { value: bigint, valueDecimals: number }
const encoded = encodeReputationValue('99.77');
// { value: 9977n, valueDecimals: 2, normalized: '99.77' }

const neg = encodeReputationValue('-15.5');
// { value: -155n, valueDecimals: 1, normalized: '-15.5' }

const raw = encodeReputationValue(9977n, 2);
// { value: 9977n, valueDecimals: 2, normalized: '99.77' }

// Decode: bigint + decimals -> string or number
decodeToDecimalString(9977n, 2);   // '99.77'
decodeToDecimalString(-155n, 1);   // '-15.5'
decodeToNumber(9977n, 2);          // 99.77

// Limits: max 6 decimal places, clamped to i64 range

### 17. Canonical JSON & Signing Utilities

import {
  canonicalizeJson,
  normalizeSignData,
  createNonce,
} from '8004-solana';

// RFC 8785 canonical JSON (deterministic key ordering, no whitespace)
canonicalizeJson({ b: 2, a: 1 });  // '{"a":1,"b":2}'

// Normalize data for signing (handles BigInt, PublicKey, Date, Buffer)
const normalized = normalizeSignData({
  amount: 100n,           // -> { $bigint: '100' }
  key: somePubkey,        // -> { $pubkey: 'base58...' }
  when: new Date(),       // -> { $date: 'ISO...' }
  data: Buffer.from([1]), // -> { $bytes: 'AQ==', encoding: 'base64' }
});

// Cryptographic nonce generation (base58-encoded random bytes)
const nonce = createNonce();     // 16 bytes default
const nonce32 = createNonce(32); // 32 bytes

### 18. IPFS Operations

// Add data
const jsonCid = await ipfs.addJson({ key: 'value' });
const rawCid = await ipfs.add('raw string data');
const fileCid = await ipfs.addFile('./image.png');

// Add registration file (normalizes and formats)
const registrationCid = await ipfs.addRegistrationFile(registrationFile);

// Retrieve
const data = await ipfs.get(jsonCid);              // raw string
const json = await ipfs.getJson(jsonCid);          // parsed JSON
const reg = await ipfs.getRegistrationFile(registrationCid); // RegistrationFile

// Supports ipfs:// prefix
const ipfsPrefixedData = await ipfs.get('ipfs://QmAbc...');

// Pin/unpin
await ipfs.pin(fileCid);
await ipfs.unpin(fileCid);

// Cleanup
await ipfs.close();

### 19. Server Mode (skipSend)

For browser wallets or external signing:

// Get unsigned transaction
const assetKeypair = Keypair.generate();
const prepared = await sdk.registerAgent(uri, undefined, {
  skipSend: true,
  signer: ownerPubkey,              // required when SDK has no signer
  assetPubkey: assetKeypair.publicKey, // required in skipSend mode
});
// prepared.transaction -> base64 serialized unsigned transaction
// prepared.signer -> base58 of the required signer

// For agent wallet (browser wallet flow)
const { message, complete } = await sdk.prepareSetAgentWallet(
  assetPubkey,
  walletPubkey,
  { signer: ownerPubkey } // optional if SDK was initialized with signer
);
const signature = await phantomWallet.signMessage(message);
await complete(signature);

All write methods accept { skipSend: true } in their options.

### 20. Indexer Client (Direct Access)

const indexer = sdk.getIndexerClient();

// Check availability
const available = await sdk.isIndexerAvailable();

// Direct queries
const agents = await indexer.getAgentsByOwner('base58...');
const feedbacks = await indexer.getFeedbacks('base58...', { limit: 100 });
const leaderboard = await indexer.getLeaderboard({ minTier: 3 });

### Wait for indexer sync after write

await sdk.giveFeedback(assetPubkey, feedbackParams);

// Poll until indexer catches up (returns true if synced, false on timeout)
const synced = await sdk.waitForIndexerSync(
  async () => {
    const fbs = await sdk.getFeedbacksFromIndexer(assetPubkey);
    return fbs.length >= expectedCount;
  },
  { timeout: 30000 }  // ms, default 30s
);

### 21. Error Handling

import {
  IndexerError,
  IndexerUnavailableError,
  IndexerTimeoutError,
  IndexerRateLimitError,
  UnsupportedRpcError,
  RpcNetworkError,
} from '8004-solana';

try {
  const agents = await sdk.getAllAgents();
} catch (e) {
  if (e instanceof UnsupportedRpcError) {
    // Default RPC doesn't support getProgramAccounts
    // Use Helius, QuickNode, or Alchemy
  }
  if (e instanceof IndexerUnavailableError) {
    // Indexer is down, SDK falls back to RPC if indexerFallback=true
  }
  if (e instanceof IndexerRateLimitError) {
    // Back off and retry
  }
}

### Methods requiring premium RPC

getAllAgents(), getAgentsByOwner(), getCollectionAgents(), getCollections()

Indexer-backed reads (readAllFeedback(), getClients(), getLastIndex(), readResponses()) do not require premium RPC, but they do require a reachable indexer.

### 22. Operation Costs (Solana devnet)

OperationCostNotesregisterAgent()~0.00651 SOLIncludes ATOM auto-initgiveFeedback() (1st for agent)~0.00332 SOLCreates reputation PDAgiveFeedback() (subsequent)~0.00209 SOLFeedback PDA onlysetMetadata() (1st key)~0.00319 SOLPDA rentsetMetadata() (update)~0.000005 SOLTX fee onlyappendResponse() (1st)~0.00275 SOLResponse + index PDAsappendResponse() (subsequent)~0.00163 SOLResponse PDA onlyrevokeFeedback()~0.000005 SOLTX fee onlydeleteMetadata()recovers rentReturns lamports to owner

### Monitor agent health

const report = await sdk.isItAlive(assetPubkey);
if (report.status !== 'live') {
  await sdk.giveFeedback(assetPubkey, {
    value: 0,
    valueDecimals: 0,
    tag1: Tag.reachable,
    score: 0,
    feedbackUri: \`ipfs://${alertCid}\`,
  });
}

### Periodic uptime reporting

const uptimePercent = calculateUptime(); // your logic
await sdk.giveFeedback(assetPubkey, {
  value: uptimePercent.toFixed(2),  // "99.75" auto-encodes
  tag1: Tag.uptime,
  tag2: Tag.day,
  feedbackUri: \`ipfs://${reportCid}\`,
});

### Trust-gated interaction

const tier = await sdk.getTrustTier(assetPubkey);
if (tier < TrustTier.Silver) {
  throw new Error('Agent trust too low for this operation');
}

### x402 payment feedback (full flow)

// 1. Build the feedback file JSON (off-chain proof of payment)
const feedbackFile = {
  version: '1.0',
  type: 'x402-feedback',
  agent: assetPubkey.toBase58(),
  client: clientPubkey.toBase58(),
  endpoint: '/api/generate',
  timestamp: new Date().toISOString(),
  proofOfPayment: {
    txHash: 'base58-tx-signature...',
    fromAddress: clientPubkey.toBase58(),
    toAddress: agentWalletPubkey.toBase58(),
    amount: '0.001',
    token: 'SOL',
    chainId: await sdk.chainId(),   // 'solana-devnet'
  },
  settlement: {
    success: true,
    network: 'solana',
    settledAt: new Date().toISOString(),
  },
  result: {
    delivered: true,
    latencyMs: 230,
    quality: 'good',
  },
};

// 2. Upload to IPFS
const feedbackCid = await ipfs.addJson(feedbackFile);

// 3. Optionally compute content hash for SEAL integrity
const feedbackFileHash = await SolanaSDK.computeHash(
  JSON.stringify(feedbackFile)
);

// 4. Submit on-chain feedback with proof link
await sdk.giveFeedback(assetPubkey, {
  value: '100.00',
  tag1: Tag.x402ResourceDelivered,
  tag2: Tag.x402Svm,
  score: 95,
  endpoint: '/api/generate',
  feedbackUri: \`ipfs://${feedbackCid}\`,
  feedbackFileHash,  // links file content to on-chain SEAL
});

// Agent-side: report good payer
await sdk.giveFeedback(clientAgentPubkey, {
  value: '1',
  valueDecimals: 0,
  tag1: Tag.x402GoodPayer,
  tag2: Tag.x402Svm,
  score: 100,
  feedbackUri: \`ipfs://${payerProofCid}\`,
});

### Verify before trusting indexer data

const integrity = await sdk.verifyIntegrity(assetPubkey);
if (!integrity.trustworthy) {
  console.warn(\`Indexer data not trustworthy: ${integrity.status}\`);
  // Fall back to on-chain queries
}

### 24. Program IDs

import {
  PROGRAM_ID,            // Agent Registry: 8oo48pya1SZD23ZhzoNMhxR2UGb8BRa41Su4qP9EuaWm
  MPL_CORE_PROGRAM_ID,   // Metaplex Core: CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d
  ATOM_ENGINE_PROGRAM_ID, // ATOM: AToM1iKaniUCuWfHd5WQy5aLgJYWMiKq78NtNJmtzSXJ
} from '8004-solana';
## Trust
- Source: tencent
- Verification: Indexed source record
- Publisher: MonteCrypto999
- Version: 1.0.0
## Source health
- Status: healthy
- Source download looks usable.
- Yavira can redirect you to the upstream package for this source.
- Health scope: source
- Reason: direct_download_ok
- Checked at: 2026-04-30T16:55:25.780Z
- Expires at: 2026-05-07T16:55:25.780Z
- Recommended action: Download for OpenClaw
## Links
- [Detail page](https://openagent3.xyz/skills/solana-agent-registry)
- [Send to Agent page](https://openagent3.xyz/skills/solana-agent-registry/agent)
- [JSON manifest](https://openagent3.xyz/skills/solana-agent-registry/agent.json)
- [Markdown brief](https://openagent3.xyz/skills/solana-agent-registry/agent.md)
- [Download page](https://openagent3.xyz/downloads/solana-agent-registry)