@brainai/satp-v3
v3.5.1
Published
Solana Agent Token Protocol V3 — TypeScript SDK for on-chain agent identity, reputation, validation, reviews, and attestations
Maintainers
Readme
@brainai/satp-v3
Solana Agent Token Protocol V3 — TypeScript SDK
On-chain identity, reputation, reviews, attestations, and validation for AI agents on Solana.
Install
npm install @brainai/satp-v3 @solana/web3.jsQuick Start
import { SatpV3Client, resolveAgent, trustTier } from '@brainai/satp-v3';
// Initialize client
const client = new SatpV3Client('https://api.devnet.solana.com');
// Resolve agent → on-chain PDA
const pda = resolveAgent('agent_brainforge');
console.log('PDA:', pda.toBase58());
// Check if agent exists on-chain
const exists = await client.agentExists('agent_brainforge');
// Get full agent summary
const summary = await client.getAgentSummary('agent_brainforge');
console.log(summary);
// { exists: true, pda: PublicKey, reviewCount: 3, linkedWalletCount: 1 }DID Resolution
import { resolveDid } from '@brainai/satp-v3/did';
const didDoc = await resolveDid('did:agentfolio:agent_brainforge', {
rpcUrl: 'https://api.devnet.solana.com'
});PDA Derivation
All PDA seeds match the on-chain programs exactly:
import {
deriveGenesisPda,
deriveLinkedWalletPda,
deriveReviewPda,
deriveAttestationPda,
deriveNameRegistryPda,
deriveMintTrackerPda,
deriveReputationAuthorityPda,
deriveValidationAuthorityPda,
} from '@brainai/satp-v3';
const [genesisPda, bump] = deriveGenesisPda('agent_brainforge');
const [namePda] = deriveNameRegistryPda('brainForge');Utilities
import {
reputationPct, verificationLabel, trustTier, isBorn,
isAttestationValid, attestationTypeLabel,
escrowStatusLabel, escrowRemaining, isEscrowExpired
} from '@brainai/satp-v3';
// Reputation score → percentage
reputationPct(genesisRecord); // "45.50"
// Verification level → label
verificationLabel(3); // "Enhanced"
// Trust tier from score
trustTier(350); // { tier: "L4", label: "Established" }
// Attestation validation
isAttestationValid(attestation); // true if verified + non-revoked + non-expired
attestationTypeLabel("github"); // "GitHub Identity"
// Escrow utilities
escrowStatusLabel(EscrowStatus.Active); // "Active"
escrowRemaining(escrow); // lamports remaining
isEscrowExpired(escrow); // true if past deadlineTrust Profile (one call → full picture)
const profile = await client.getTrustProfile('agent_brainforge');
// {
// exists: true,
// pda: PublicKey,
// verificationLevel: { level: 3, label: "Enhanced" },
// attestationSummary: { total: 5, verified: 4, valid: 3, uniqueTypes: ["github", "kyc"] },
// reviewCount: 12,
// linkedWalletCount: 2
// }Transaction Builders (NEW in 3.5.0)
Build unsigned transactions for all SATP V3 instructions. Sign with any wallet adapter.
import { SatpV3Builders, LAMPORTS_PER_SOL } from '@brainai/satp-v3';
const builders = new SatpV3Builders('https://api.devnet.solana.com');
// Create an agent identity
const tx = await builders.createIdentity({
agentId: 'agent_mybot',
name: 'MyBot',
description: 'An autonomous trading assistant',
category: 'finance',
capabilities: ['trading', 'analysis'],
metadataUri: 'https://example.com/meta.json',
creator: walletPublicKey,
});
// Sign and send: await connection.sendTransaction(tx, [walletKeypair]);
// Create an escrow (client pays agent for work)
const { transaction, escrowPda, nonce } = await builders.createEscrow({
client: clientWallet,
agentWallet: agentWallet,
agentId: 'agent_mybot',
arbiter: arbiterWallet,
amount: 1_000_000_000n, // 1 SOL
description: 'Build a trading bot',
deadline: Math.floor(Date.now() / 1000) + 86400, // 24h
});
// Agent submits work proof
const submitTx = await builders.submitWork({
escrowPda,
agent: agentWallet,
workProof: 'https://github.com/org/repo/pull/42',
});
// Client releases funds
const releaseTx = await builders.releaseEscrow({
escrowPda,
client: clientWallet,
agent: agentWallet,
});
// Create a review
const reviewTx = await builders.createReview({
agentId: 'agent_mybot',
reviewer: reviewerWallet,
rating: 5,
reviewText: 'Excellent work, fast delivery!',
});
// Create an attestation (KYC, GitHub, etc.)
const attTx = await builders.createAttestation({
agentId: 'agent_mybot',
issuer: issuerWallet,
attestationType: 'github',
proofData: 'https://github.com/user',
expiresAt: Math.floor(Date.now() / 1000) + 365 * 86400, // 1 year
});Builder Methods
Identity Builders
| Method | Description |
|--------|-------------|
| createIdentity(params) | Create new Genesis Record |
| updateIdentity(params) | Update identity fields (null = no change) |
| burnToBecome(params) | Activate via burn-to-become |
| linkWallet(params) | Link external wallet |
| unlinkWallet(params) | Unlink wallet |
| registerName(params) | Register unique name |
| releaseName(params) | Release registered name |
| initMintTracker(params) | Initialize mint tracker |
| recordMint(params) | Record mint event |
| proposeAuthority(params) | Start authority transfer |
| acceptAuthority(params) | Accept authority transfer |
| cancelAuthorityTransfer(params) | Cancel pending transfer |
| deactivateIdentity(params) | Deactivate identity |
| reactivateIdentity(params) | Reactivate identity |
Escrow Builders
| Method | Description |
|--------|-------------|
| createEscrow(params) | Create escrow → returns {transaction, escrowPda, nonce} |
| submitWork(params) | Submit work proof (string or 32-byte hash) |
| releaseEscrow(params) | Release all funds to agent |
| partialRelease(params) | Release partial amount (milestones) |
| cancelEscrow(params) | Cancel (after deadline, no work submitted) |
| closeEscrow(params) | Close settled escrow (returns rent) |
| extendDeadline(params) | Extend escrow deadline |
| raiseDispute(params) | Raise dispute (client or agent) |
| resolveDispute(params) | Arbiter resolves dispute |
Reviews Builders
| Method | Description |
|--------|-------------|
| initReviewCounter(params) | Init counter (required before first review) |
| createReview(params) | Create review (1-5 rating) |
| updateReview(params) | Update review (optional fields) |
| deleteReview(params) | Delete review |
Attestation Builders
| Method | Description |
|--------|-------------|
| createAttestation(params) | Create attestation |
| verifyAttestation(params) | Mark as verified |
| revokeAttestation(params) | Revoke attestation |
Programs
| Program | Address |
|---------|---------|
| identity_v3 | GTppU4E44BqXTQgbqMZ68ozFzhP1TLty3EGnzzjtNZfG |
| reviews_v3 | r9XX4frcqxxAZ6Au9V5PA3EAxs1zoNckqLLmoSRcNr4 |
| reputation_v3 | 2Lz7KzMvKdrGeAuS8WPHu7jK2yScrnKVgacpYVEuDjkJ |
| attestations_v3 | 6Xd1dAQJPvQRJ4Ntr6LtPTjDjPUZ8nfnmYLZaZ2DtrdD |
| validation_v3 | 6rYRiCYidJYV7QvKrzKGgNu4oMh6BAvynked69R7xMbV |
| escrow_v3 | HXCUWKR2NvRcZ7rNAJHwPcH6QAAWaLR4bRFbfyuDND6C |
API Reference
Client Methods
Identity
| Method | Returns | Description |
|--------|---------|-------------|
| getGenesis(agentId) | {pda, data} \| null | Fetch raw Genesis Record |
| agentExists(agentId) | boolean | Check if agent is on-chain |
| getNameRegistry(name) | {pda, data} \| null | Look up name registration |
| isNameTaken(name) | boolean | Check name availability |
| getMintTracker(agentId) | {pda, data} \| null | Get mint tracker |
| getLinkedWallets(agentId) | [{pubkey, data}] | All linked wallets |
| getAgentSummary(agentId) | {exists, pda, reviewCount, linkedWalletCount} | Full summary |
Reviews
| Method | Returns | Description |
|--------|---------|-------------|
| getReviewCount(agentId) | number \| null | Total review count |
| getReviews(agentId) | [{pubkey, data}] | All reviews |
Attestations (NEW in 3.4.0)
| Method | Returns | Description |
|--------|---------|-------------|
| getAttestation(pda) | {pda, data} \| null | Fetch attestation by PDA |
| getAttestationByParams(agentId, issuer, type) | {pda, data} \| null | Fetch by known parameters |
| getAttestationsByAgent(agentId) | [{pubkey, data}] | All attestations for an agent |
| getAttestationsByIssuer(issuer) | [{pubkey, data}] | All attestations by an issuer |
| getAttestationSummary(agentId) | {total, verified, valid, uniqueTypes, typeCounts} | Attestation breakdown |
Validation (NEW in 3.4.0)
| Method | Returns | Description |
|--------|---------|-------------|
| getVerificationLevel(agentId) | {level, label} \| null | Current verification level |
| getTrustProfile(agentId) | {exists, verificationLevel, attestationSummary, reviewCount, ...} | Complete trust profile |
Escrow
| Method | Returns | Description |
|--------|---------|-------------|
| getEscrow(pda) | {pda, data} \| null | Fetch escrow by PDA |
| getEscrowByParams(client, description, nonce) | {pda, data} \| null | Fetch by parameters |
| getEscrowsByClient(client) | [{pubkey, data}] | All escrows by client |
| getEscrowsByAgent(agent) | [{pubkey, data}] | All escrows for agent wallet |
| getEscrowsByAgentId(agentId) | [{pubkey, data}] | All escrows by agent ID |
PDA Functions
| Function | Seeds | Program |
|----------|-------|---------|
| deriveGenesisPda(agentId) | ["genesis", sha256(agentId)] | identity |
| deriveLinkedWalletPda(genesis, wallet) | ["linked_wallet", genesis, wallet] | identity |
| deriveNameRegistryPda(name) | ["name_registry", sha256(lower(name))] | identity |
| deriveMintTrackerPda(genesis) | ["mint_tracker", genesis] | identity |
| deriveReviewPda(agentId, reviewer) | ["review_v3", sha256(agentId), reviewer] | reviews |
| deriveReviewCounterPda(agentId) | ["review_counter_v3", sha256(agentId)] | reviews |
| deriveAttestationPda(agentId, issuer, type) | ["attestation_v3", sha256(agentId), issuer, type] | attestations |
| deriveReputationAuthorityPda() | ["reputation_v3_authority"] | reputation |
| deriveValidationAuthorityPda() | ["validation_v3_authority"] | validation |
| deriveEscrowPda(client, descHash, nonce) | ["escrow_v3", client, descHash, nonce] | escrow |
Borsh Deserializers (NEW in 3.5.0)
Parse raw on-chain account data into typed TypeScript objects:
import {
deserializeGenesis,
deserializeLinkedWallet,
deserializeReview,
deserializeAttestation,
deserializeEscrow,
tryDeserialize,
} from '@brainai/satp-v3';
// Fetch raw data and deserialize
const raw = await client.getGenesis('agent_brainforge');
if (raw) {
const genesis = deserializeGenesis(raw.data);
console.log(genesis.agentName); // "brainForge"
console.log(genesis.verificationLevel); // 3
console.log(genesis.isActive); // true
}
// Batch-safe: tryDeserialize returns null instead of throwing
const reviews = await client.getReviews('agent_brainforge');
const parsed = reviews
.map(r => tryDeserialize(deserializeReview, r.data))
.filter(Boolean);Deserializer Functions
| Function | Returns | Source Program |
|----------|---------|----------------|
| deserializeGenesis(data) | GenesisRecord | identity_v3 |
| deserializeLinkedWallet(data) | LinkedWallet | identity_v3 |
| deserializeNameRegistry(data) | NameRegistry | identity_v3 |
| deserializeMintTracker(data) | MintTracker | identity_v3 |
| deserializeReview(data) | ReviewV3 | reviews_v3 |
| deserializeReviewCounter(data) | ReviewCounterV3 | reviews_v3 |
| deserializeAttestation(data) | AttestationV3 | attestations_v3 |
| deserializeEscrow(data) | EscrowV3 | escrow_v3 |
| tryDeserialize(fn, data) | T \| null | (wrapper) |
License
MIT © brainAI
