New:Microsoft Teams Notifications Are Now Available in Socket.Learn more
Get Started

@brainai/satp-client

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@brainai/satp-client

SATP client SDK surface prepared for release-candidate review; publish only after the release packet passes.

Source
npmnpm
Version
2.0.5
Version published
Weekly downloads
12
-63.64%
Maintainers
1
Weekly downloads
 
Created
Source

SATP V3 SDK - @brainai/satp-client

Solana Agent Trust Protocol - JavaScript/TypeScript SDK for reading and building reviewed SATP V3 program interactions.

Current stable npm package: @brainai/satp-client@2.0.3 | rc dist-tag: @brainai/satp-client@2.0.2 | Programs: 6

Installation

Choose stable, rc, or Git based on what the consumer needs to prove:

ChannelUse whenCommand
Stable npmDefault production-style consumption of the stable public package.npm install @brainai/satp-client@2.0.3
Historical rc exact versionExplicit HQ-assigned reproduction or lockfile evidence for the historical pre-stable artifact.npm install @brainai/satp-client@2.0.2
Release candidate tagExplicit HQ-assigned rc validation where a moving dist-tag is acceptable and the task names the tag as the target.npm install @brainai/satp-client@rc
Reviewed Git commitPR coordination or source-review installs tied to an exact SATP commit.npm install git+https://github.com/brainAI-bot/satp.git#<SATP_COMMIT>

Registry readback on 2026-07-26 shows npm latest resolves to @brainai/satp-client@2.0.3 and the rc dist-tag resolves to 2.0.2. Stable consumers should use latest/2.0.3 unless HQ assigns an explicit release-candidate validation task.

For stable consumer installs, pin the current published npm package:

npm install @brainai/satp-client@2.0.3

For rc validation:

npm install @brainai/satp-client@2.0.2

Use @rc only when the HQ task names the moving tag itself as the validation target:

npm install @brainai/satp-client@rc

For branch-only development or PR review, pin an explicit SATP Git commit:

npm install git+https://github.com/brainAI-bot/satp.git#<SATP_COMMIT>

The old 0.0.0-extraction label was extraction-branch metadata and is not the current consumer package. Do not treat branch-only Git installs as npm latest.

Mainnet program IDs are present for the reviewed V3 registry, but availability is not action approval. Mainnet writes, deploys, keypair use, authority changes, value-bearing escrow actions, npm promotion, and production claims still require a separate HQ approval and the relevant owner-gated runbook. See docs/mainnet-authority-decision-packet-6c8a5545.md for the public authority decision packet.

RC-S6 semantic uncertainty outcomes are covered by the offline conformance gate merged in 93db1b3 (PR #53, [#43394290]) and runnable with npm run test:conformance:rc-s6 from the repository root. Treat positive fixtures as deterministic SDK/schema compatibility only. Treat stale, revoked, malformed, unsupported-issuer, score-meaning, review-weight, escrow-reference, and AgentFolio copy-boundary fixtures as warning or fail-closed outcomes; do not convert them into verified badges, ranking, eligibility, payment state, escrow readiness, mainnet readiness, npm latest adoption, or product approval.

Runtime dependency: @solana/web3.js ^1.98.4

Quick Start

For the root consumer quickstart covering stable npm, rc validation, Git-review pins, read-only trust packets, conformance checks, and network boundaries, see docs/quickstart.md.

const { SATPV3SDK } = require('@brainai/satp-client');

// Initialize (devnet by default)
const sdk = new SATPV3SDK({ network: 'devnet' });

// Check if an agent has an identity
const exists = await sdk.hasIdentity('brainChain');
console.log(exists); // true

// Read a Genesis Record
const record = await sdk.getGenesisRecord('brainChain');
console.log(record.agentName, record.category, record.isActive);

// Build a transaction (unsigned — sign with your wallet)
const tx = await sdk.buildCreateIdentity(creatorPubkey, 'myAgent', {
  agentName: 'My Agent',
  description: 'An AI agent on Solana',
  category: 'assistant',
  capabilities: ['chat', 'code'],
  metadataUri: 'https://example.com/meta.json',
});
// Sign and send tx with your wallet...

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        SATP V3 SDK                              │
├─────────────┬──────────────┬──────────────┬─────────────────────┤
│ Identity    │ Reviews      │ Attestations │ Escrow              │
│ (20 methods)│ (7 methods)  │ (3 methods)  │ (10 methods)        │
├─────────────┼──────────────┼──────────────┤                     │
│ Reputation  │ Validation   │ Migration    │                     │
│ (1 method)  │ (1 method)   │ (1 method)   │                     │
├─────────────┴──────────────┴──────────────┴─────────────────────┤
│ PDA Derivation  │  Borsh Serialization  │  RPC Helpers          │
└─────────────────┴───────────────────────┴───────────────────────┘

Programs & Program IDs

ProgramDevnetDescription
identity_v3GTppU4E44BqXTQgbqMZ68ozFzhP1TLty3EGnzzjtNZfGAgent identity, names, wallets, face/birth
reviews_v3r9XX4frcqxxAZ6Au9V5PA3EAxs1zoNckqLLmoSRcNr4Peer reviews with 1-5 star ratings
attestations_v36Xd1dAQJPvQRJ4Ntr6LtPTjDjPUZ8nfnmYLZaZ2DtrdDThird-party attestations & proofs
reputation_v32Lz7KzMvKdrGeAuS8WPHu7jK2yScrnKVgacpYVEuDjkJWeighted reputation scoring (CPI → identity)
validation_v36rYRiCYidJYV7QvKrzKGgNu4oMh6BAvynked69R7xMbVValidation level computation (CPI → identity)
escrow_v3B1Se8SPx7GLUisa4LYeXY1tDZy5TviJrsV2yMLgqUXmgSOL escrow for agent jobs

API Reference

Read-only Trust Packet Helpers

buildSatpTrustPacket(opts) creates a deterministic, offline trust packet for consumer preflight and release-packet review. It uses the same inputs as prepareIdentityAttestationRequest, then includes the derived program IDs, Genesis PDA, attestation PDA, request hash, and the unsigned request object. The packet is intentionally read-only: flags.signingRequired, flags.transactionRequired, flags.writesRequired, and flags.livePaymentRequired are all false; instructions and signers are empty; and transaction is null.

const {
  buildSatpTrustPacket,
  validateSatpTrustPacket,
} = require('@brainai/satp-client');

const trustPacket = buildSatpTrustPacket({
  subjectWallet: '11111111111111111111111111111111',
  agentId: 'brainChain',
  claimType: 'identity',
  metadataHash: '93d122f8879fe87c186c10a00db8fbc80a73cecd2ede44b9ffa6410be3c2b805',
  network: 'devnet',
});

const validation = validateSatpTrustPacket(trustPacket);
if (!validation.ok) throw new Error(validation.errors.join('; '));

validateSatpTrustPacket(packet) returns { ok, errors }. Validation requires packetType: 'satp-trust-packet' and mode: 'offline-readonly-trust-packet', rejects changed read-only flags, and re-derives the expected packet so tampered PDA, program, request, or hash fields surface as explicit errors.

x402 Discovery Evidence Lookup Helpers

parseX402DiscoveryMetadata(input), buildX402EvidenceLookup(input, opts), and buildRuntimePolicyActionDescriptorFromX402Discovery(input, opts) map x402 discovery metadata into SATP runtime policy evidence lookup data. The helpers are read-only: x402 payment metadata can identify where evidence may be fetched, but it is discovery/evidence lookup only and never authorizes SATP action execution, spending, live payment, signing, transactions, or host policy bypass.

Run the offline example:

node packages/satp-client/examples/x402-discovery-evidence-lookup.js

The example parses discovery metadata, builds an evidence lookup descriptor, and builds a runtime policy action descriptor. It asserts X402_PAYMENT_IS_NOT_ACTION_AUTHORIZATION plus paymentAuthorization: false, actionAuthorization: false, spendAuthorized: false, and livePaymentRequired: false.

Runtime Policy Adapter Helper

createRuntimePolicyAdapter(opts) provides a host-oriented wrapper around the offline runtime policy helpers:

const { createRuntimePolicyAdapter } = require('@brainai/satp-client');

const adapter = createRuntimePolicyAdapter({
  defaultActionType: 'mcp_protected_tool',
  now: () => '2026-05-21T00:00:00Z',
  policy: { minimumTrustScore: 70, maxAutoSpendUsd: 0 },
});

const action = adapter.action({
  resource: 'mcp://protected/readiness',
  capability: 'mcp:read',
});
const result = adapter.evaluate(identityPayload, action);
const trace = adapter.auditTrace(identityPayload, action, { result });
const summary = adapter.explain(result);

The adapter only builds local descriptors, local decisions, redacted audit traces, and display-safe reason summaries. It does not call RPC, read keypairs, sign, send transactions, approve x402 spend, treat payment as action authorization, write Solana state, deploy, publish, or restart production.

Wallet-Control Challenge Helpers

buildWalletControlChallenge(opts) creates a canonical, offline challenge that binds an agent ID to a Solana wallet. It derives the SATP V3 Genesis PDA and linked-wallet PDA from agentId, wallet, and network, includes a nonce and expiry, and returns plain JSON. It does not connect to RPC, read keypairs, create transactions, sign, send, deploy, or mutate chain state.

canonicalWalletControlChallenge(challenge) returns the exact UTF-8 message a wallet signs. verifyWalletControlChallengeSignature(opts) verifies a 64-byte Ed25519 signature against the challenge wallet and fails closed for mismatched wallets, signatures, agent IDs, PDAs, domain, audience, expiry, and replayed nonces supplied by your replay cache.

const {
  buildWalletControlChallenge,
  canonicalWalletControlChallenge,
  verifyWalletControlChallengeSignature,
} = require('@brainai/satp-client');

const challenge = buildWalletControlChallenge({
  agentId: 'brainChain',
  wallet: walletPublicKey,
  audience: 'my-service',
  nonce: crypto.randomBytes(16).toString('hex'),
});

// Ask the wallet to sign this exact canonical string.
const message = canonicalWalletControlChallenge(challenge);

const verification = verifyWalletControlChallengeSignature({
  challenge,
  signature,
  expectedWallet: walletPublicKey,
  expectedAgentId: 'brainChain',
  expectedAudience: 'my-service',
  usedNonces: replayCache,
});
if (!verification.ok) throw new Error(verification.errors.join('; '));

Constructor

const sdk = new SATPV3SDK({ network, rpcUrl });
// network: 'devnet' (default) or 'mainnet'.
// rpcUrl: optional custom RPC endpoint

Identity Methods (20)

MethodDescription
buildCreateIdentity(creator, agentId, meta)Create a new agent identity (Genesis Record)
buildBurnToBecome(authority, agentId, faceImage, faceMint, faceBurnTx)Burn NFT to set agent's face (birth ritual)
buildUpdateIdentity(authority, agentId, updates)Update mutable fields (description, capabilities, metadata)
buildProposeAuthority(authority, agentId, newAuthority)Propose authority transfer (2-step)
buildAcceptAuthority(newAuthority, agentId)Accept proposed authority transfer
buildCancelAuthorityTransfer(authority, agentId)Cancel pending authority transfer
buildRegisterName(authority, agentId, name)Register a unique name for an agent
buildReleaseName(authority, agentId, name)Release a registered name
buildLinkWallet(authority, agentId, wallet, chain, label)Link an external wallet to identity
buildUnlinkWallet(authority, agentId, wallet)Unlink an external wallet
buildInitMintTracker(authority, agentId)Initialize NFT mint tracker
buildRecordMint(authority, agentId)Record an NFT mint event
buildDeactivateIdentity(authority, agentId)Deactivate an identity
buildReactivateIdentity(authority, agentId)Reactivate a deactivated identity
getGenesisRecord(agentId)Read a Genesis Record from chain
hasIdentity(agentId)Check if an agent has an identity
getEscrowPDA(client, description, nonce)Derive escrow PDA (sync)
buildMigrateV2ToV3(v2Authority, agentId, meta)Migrate from V2 to V3 identity

Genesis Record Fields

const record = await sdk.getGenesisRecord('brainChain');
// Returns:
{
  agentIdHash: string,     // SHA-256 of agent_id
  agentName: string,       // Display name
  description: string,     // Agent description
  category: string,        // e.g. "developer", "assistant"
  capabilities: string[],  // e.g. ["solana", "code"]
  metadataUri: string,     // Off-chain metadata URL
  faceImage: string,       // Face image URL (after birth)
  faceMint: string,        // NFT mint address (after birth)
  faceBurnTx: string,      // Burn transaction signature
  genesisRecord: number,   // Unix timestamp of birth
  isBorn: boolean,         // Whether agent has completed birth ritual
  isActive: boolean,       // Whether identity is active
  authority: string,       // Current authority pubkey
  pendingAuthority: string | null,
  reputationScore: number, // CPI-updated reputation
  validationLevel: number, // CPI-updated validation
  createdAt: number,       // Unix timestamp
  updatedAt: number,       // Unix timestamp
}

Reviews Methods (7)

MethodDescription
buildInitReviewCounter(payer, agentId)Initialize review counter for an agent
buildCreateReview(reviewer, agentId, rating, text, metadata, opts)Create a 1-5 star review
buildCreateReviewWithSelfCheck(reviewer, agentId, rating, text, metadata)Create review with self-review prevention
buildUpdateReview(reviewer, reviewPDA, updates)Update an existing review
buildDeleteReview(reviewer, reviewPDA)Soft-delete a review
getReview(agentId, reviewer)Read a review from chain
getReviewCount(agentId)Get total review count for an agent
// Create a review
const tx = await sdk.buildCreateReview(
  reviewerPubkey,
  'brainChain',      // agent being reviewed
  5,                 // rating (1-5)
  'Excellent Solana dev',
  'metadata',
  { category: 'development' }
);

Attestations Methods (3)

MethodDescription
buildCreateAttestation(issuer, agentId, type, proofData, expiresAt)Issue an attestation
buildVerifyAttestation(issuer, attestationPDA)Mark attestation as verified
buildRevokeAttestation(issuer, attestationPDA)Revoke an attestation
// Issue a KYC attestation
const tx = await sdk.buildCreateAttestation(
  issuerPubkey,
  'brainChain',
  'kyc',             // attestation type
  'proof-hash-here',
  Math.floor(Date.now()/1000) + 86400 * 365 // expires in 1 year
);

Reputation & Validation Methods (2)

MethodDescription
buildRecomputeReputation(caller, agentId, reviewAccounts)Recompute reputation score from reviews (CPI → identity)
buildRecomputeLevel(caller, agentId, attestationAccounts)Recompute validation level from attestations (CPI → identity)

These use Cross-Program Invocation to update fields directly on the Genesis Record.

Escrow Methods (10)

App-agnostic escrow builders for downstream applications that need unsigned SATP escrow transactions. Product-specific marketplace records, fees, job workflow, moderation, and display copy stay in the consuming application.

MethodDescription
buildCreateEscrow(client, agentWallet, agentId, amount, description, deadline, nonce, opts)Create SOL escrow for a job
buildSubmitWork(agent, escrowPDA, workProof)Agent submits work proof
buildEscrowRelease(client, agent, escrowPDA)Client releases full payment
buildPartialRelease(client, agent, escrowPDA, amount)Client releases partial payment
buildCancelEscrow(client, escrowPDA)Cancel escrow (refund client)
buildRaiseDispute(signer, escrowPDA, reason)Raise a dispute
buildResolveDispute(arbiter, agent, client, escrowPDA, agentAmt, clientAmt)Arbiter resolves dispute
buildExtendDeadline(client, escrowPDA, newDeadline)Extend job deadline
buildCloseEscrow(client, escrowPDA)Close completed/cancelled escrow (reclaim rent)
getEscrow(escrowPDA)Read escrow state from chain

Escrow Lifecycle

Created → WorkSubmitted → Released (full or partial)
   ↓           ↓              ↓
Cancelled   Disputed     Closed (rent reclaimed)
               ↓
          Resolved (split)
               ↓
            Closed
// Create an escrow (0.5 SOL for a generic work agreement)
const tx = await sdk.buildCreateEscrow(
  clientPubkey,
  agentWallet,
  'brainChain',
  0.5 * 1e9,        // lamports
  'Complete agreed work',
  Math.floor(Date.now()/1000) + 86400 * 7, // 7 day deadline
  0,                 // nonce (for multiple escrows with same description)
  { arbiter: arbiterPubkey }
);

PDA Helpers (exported from v3-pda.js)

const {
  hashAgentId,                  // SHA-256 hash of agent_id string
  hashName,                     // SHA-256 hash of name string
  getGenesisPDA,                // [b"genesis_record", agent_id_hash]
  getNameRegistryPDA,           // [b"name_registry_v3", name_hash]
  getLinkedWalletPDA,           // [b"linked_wallet_v3", agent_id_hash, wallet]
  getV3MintTrackerPDA,          // [b"mint_tracker_v3", agent_id_hash]
  getV3ReviewPDA,               // [b"review_v3", agent_id_hash, reviewer]
  getV3ReviewCounterPDA,        // [b"review_counter_v3", agent_id_hash]
  getV3AttestationPDA,          // [b"attestation_v3", agent_id_hash, issuer, type_hash]
  getV3ReputationAuthorityPDA,  // [b"reputation_authority", agent_id_hash]
  getV3ValidationAuthorityPDA,  // [b"validation_authority", agent_id_hash]
  getV3EscrowPDA,               // [b"escrow_v3", client, desc_hash, nonce_le]
  getV3ProgramIds,              // Returns all 6 program IDs for network
} = require('@brainai/satp-client/src/v3-pda');

Escrow SDK Utilities (exported from v3-sdk.js)

const {
  deriveEscrowPda,    // Derive escrow PDA from params
  descriptionHash,    // SHA-256 hash of description string
  EscrowStatus,       // Enum: { Active: 0, WorkSubmitted: 1, Released: 2, Cancelled: 3, Disputed: 4, Resolved: 5 }
  escrowStatusLabel,  // Convert status number to human-readable string
  escrowRemaining,    // Calculate remaining escrow balance
  isEscrowExpired,    // Check if escrow has passed deadline
} = require('@brainai/satp-client/src/v3-sdk');

Transaction Pattern

All build* methods return an unsigned Transaction object. Your application is responsible for:

  • Setting recentBlockhash and feePayer
  • Signing with the appropriate wallet
  • Sending to the network
const tx = await sdk.buildCreateIdentity(wallet.publicKey, 'myAgent', { ... });
tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
tx.feePayer = wallet.publicKey;
tx.sign(wallet);
const sig = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(sig);

Consumer APIs

SATP core does not define or host an HTTP API. Downstream applications may wrap the SDK with their own read APIs, but those routes are consumer-owned adapters and must not be treated as SATP protocol authority.

Testing

# Unit tests (101)
node test-v3.js

# Devnet integration tests (16)
node test-v3-devnet.js

# CPI integration tests (35)
cd .. && node tests/devnet-cpi-integration.js

# Release-safety defaults and network-boundary checks
node test-release-safety.js

Network Configuration

// Devnet (default)
const sdk = new SATPV3SDK();

// Explicit devnet
const sdk = new SATPV3SDK({ network: 'devnet' });

// Custom RPC
const sdk = new SATPV3SDK({ rpcUrl: 'https://my-rpc.example.com' });

// Mainnet uses the V3 registry IDs documented in Anchor.toml [programs.mainnet].
const sdk = new SATPV3SDK({ network: 'mainnet' });

Borsh Deserialization Helpers (v3.6.0)

Zero-dependency Borsh deserialization for all 8 SATP V3 account types. Decode raw on-chain data without the borsh library.

Supported Account Types

AccountProgramDeserializer
GenesisRecordIdentity V3deserializeGenesisRecord(data)
LinkedWalletIdentity V3deserializeLinkedWallet(data)
MintTrackerIdentity V3deserializeMintTracker(data)
NameRegistryIdentity V3deserializeNameRegistry(data)
ReviewReviews V3deserializeReview(data)
ReviewCounterReviews V3deserializeReviewCounter(data)
AttestationAttestations V3deserializeAttestation(data)
EscrowV3Escrow V3deserializeEscrowV3(data)

Usage: Typed Deserialization

const { deserializeGenesisRecord, deserializeAttestation } = require('@brainai/satp-client');
const { Connection, PublicKey } = require('@solana/web3.js');

const conn = new Connection('https://api.devnet.solana.com');

// Fetch raw account and deserialize
const acct = await conn.getAccountInfo(new PublicKey('...'));
const genesis = deserializeGenesisRecord(acct.data);
console.log(genesis.agentName, genesis.reputationScore, genesis.isBorn);

Usage: Auto-detect Account Type

const { deserializeAccount } = require('@brainai/satp-client');

// Automatically detects type from 8-byte Anchor discriminator
const { type, data } = deserializeAccount(acct.data);
console.log(type);  // "GenesisRecord" | "Attestation" | "EscrowV3" | ...
console.log(data);  // Fully parsed object

Usage: Batch Deserialization (getProgramAccounts)

const { deserializeBatch, DISCRIMINATORS } = require('@brainai/satp-client');

const accounts = await conn.getProgramAccounts(REVIEWS_PROGRAM_ID);
const reviews = deserializeBatch(accounts, 'Review');
// [{ pubkey: "...", type: "Review", data: { agentId, rating, ... } }, ...]

Usage: BorshReader (Custom Deserialization)

const { BorshReader } = require('@brainai/satp-client');

// Low-level reader for custom account layouts
const r = new BorshReader(acct.data);
r.skipDiscriminator();           // skip 8-byte Anchor discriminator
const hash = r.readFixedBytes32(); // [u8; 32]
const name = r.readString();     // Borsh String
const items = r.readVecString(); // Vec<String>
const pk = r.readPubkeyBase58(); // Pubkey → base58
const opt = r.readOptionI64();   // Option<i64> → number | null

Discriminator Utilities

const { isAccountType, getAccountDiscriminator, DISCRIMINATORS } = require('@brainai/satp-client');

// Check account type before deserializing
if (isAccountType(acct.data, 'EscrowV3')) {
  const escrow = deserializeEscrowV3(acct.data);
}

// Get discriminator for filtering
const disc = getAccountDiscriminator('Attestation'); // 8-byte Buffer
// Use with getProgramAccounts memcmp filter

Security

  • All transactions are returned unsigned — the SDK never holds private keys
  • PDA derivation is deterministic and verified against on-chain seeds
  • CPI boundaries enforce program-level authorization
  • Escrow funds are held by PDA-owned accounts (no custodial risk)

License

MIT — brainAI 2026

Keywords

solana

FAQs

Package last updated on 27 Jul 2026

Related posts