Sol.College

Full lesson

agenttrust

Trust AI-agent payments before they settle.

What it does

From the project README:

[](https://www.agenttrust.tech) [](https://docs.agenttrust.tech) [](https://mcp.agenttrust.tech) [](https://www.npmjs.com/package/@agenttrust-sdk/trustgate) [](https://www.npmjs.com/package/@agenttrust-sdk/mcp) [](.github/workflows/kani-prove.yml) [](.github/workflows/) [](./LICENSE) [](https://x.com/agenttrustlabs)
Original
agenttrust-labs/agenttrust
SuperStack fork
Blockchains/agenttrust @ 21a3b11
Stars
3
Last push (original)
2026-05-31
Languages
TypeScript, MDX, Rust, CSS, JavaScript, Dockerfile
Detected stack
AnchorNext.jsweb3.js
Categories
AI & AgentsPayments
Licence
MIT
Homepage
https://www.agenttrust.tech

Architecture

413 source files. By extension: .ts ×231, .tsx ×113, .rs ×66, .js ×3.

Top-level directorySource files
web146
mcp68
programs66
trustgate59
docs-site36
examples26
tests5
status-page4

On-chain programs: programs/policy-vault, programs/trustgate, programs/validation-registry

Dapp: devnet deploy pending

⏳ Devnet deploy pending — goes live when the devnet wallet is topped up. This fork's own dapp is not deployed yet, so there is no program address or transaction to show. It is queued in dapp-queue.txt; once devnet SOL is available it is deployed, exercised with real devnet transactions, and this section switches to the live dapp at /dapps/agenttrust/. Until then, the lesson and step-by-step guide below are complete, and you can run it locally with the commands below.

Key code, explained

Excerpts chosen automatically where the code uses the most Solana concepts, pinned to the fork's commit.

agenttrust-labs/agenttrust · programs/trustgate/src/instructions/init_authority.rs L13–36 @ 21a3b11 · MIT · original
#[derive(Accounts)]#[instruction(facilitator: Pubkey)]pub struct InitAuthority<'info> {    #[account(mut)]    pub payer: Signer<'info>,     #[account(        init,        payer = payer,        space = 8 + TrustGateAuthority::INIT_SPACE,        seeds = [TrustGateAuthority::SEED_PREFIX, facilitator.as_ref()],        bump,    )]    pub authority: Account<'info, TrustGateAuthority>,     pub system_program: Program<'info, System>,} pub fn handler(ctx: Context<InitAuthority>, facilitator: Pubkey) -> Result<()> {    let now_slot = Clock::get()?.slot;    let auth = &mut ctx.accounts.authority;    auth.facilitator = facilitator;    auth.bump = ctx.bumps.authority;    auth._pad0 = [0u8; 7];
  1. Line 17 pub payer: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 20 init,: Creates and pays for a new account. Space and payer must be specified.
  3. Line 23 seeds = [TrustGateAuthority::SEED_PREFIX, facilitator.as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 24 bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  5. Line 32 let now_slot = Clock::get()?.slot;: Reads on-chain time from the Clock sysvar.
agenttrust-labs/agenttrust · programs/validation-registry/src/instructions/register_namespace.rs L25–48 @ 21a3b11 · MIT · original
    #[account(mut)]    pub creator: Signer<'info>,     #[account(        init,        payer = creator,        space = 8 + CapabilityNamespace::INIT_SPACE,        seeds = [CapabilityNamespace::SEED_PREFIX, namespace_hash.as_ref()],        bump,    )]    pub namespace: Account<'info, CapabilityNamespace>,     pub system_program: Program<'info, System>,} pub fn handler(    ctx: Context<RegisterNamespace>,    namespace_hash: [u8; 32],    name: String,    version: String,    schema_uri: String,) -> Result<()> {    require!(        name.len() >= MIN_NAME_LEN,
  1. Line 26 pub creator: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 29 init,: Creates and pays for a new account. Space and payer must be specified.
  3. Line 32 seeds = [CapabilityNamespace::SEED_PREFIX, namespace_hash.as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 33 bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  5. Line 47 require!(: An explicit validation that aborts the instruction with an error.
agenttrust-labs/agenttrust · programs/policy-vault/src/instructions/init_authority.rs L13–36 @ 21a3b11 · MIT · original
use crate::errors::PolicyVaultError;use crate::state::PolicyAuthority; #[derive(Accounts)]#[instruction(payer_agent_asset: Pubkey)]pub struct InitAuthority<'info> {    #[account(mut)]    pub payer: Signer<'info>,     #[account(        init,        payer = payer,        space = 8 + PolicyAuthority::INIT_SPACE,        seeds = [PolicyAuthority::SEED_PREFIX, payer_agent_asset.as_ref()],        bump,    )]    pub policy_authority: Account<'info, PolicyAuthority>,     pub system_program: Program<'info, System>,} pub fn handler(    ctx: Context<InitAuthority>,    payer_agent_asset: Pubkey,
  1. Line 20 pub payer: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 23 init,: Creates and pays for a new account. Space and payer must be specified.
  3. Line 26 seeds = [PolicyAuthority::SEED_PREFIX, payer_agent_asset.as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 27 bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
agenttrust-labs/agenttrust · programs/policy-vault/src/instructions/gate_payment.rs L37–60 @ 21a3b11 · MIT · original
    /// SECURITY: in v1, ANY signer can call gate_payment. The composer's    /// state writes (Spending counters + VelocityLedger cumulative) are    /// therefore exposed to a denial-of-service attack: a hostile caller    /// could exhaust the daily / weekly / window budget via spurious calls.    /// v1.1 adds a facilitator allowlist on `PolicyAccount`. For the v1    /// hackathon submission, gate_payment is invoked by TrustGate (Phase 6),    /// which itself is invoked by trusted x402 facilitators.    pub caller: Signer<'info>,     #[account(        mut,        seeds = [PolicyAccount::SEED_PREFIX, payer_agent_asset.as_ref(), &policy_id.to_le_bytes()],        bump = policy_account.bump,    )]    pub policy_account: Account<'info, PolicyAccount>,     #[account(        mut,        seeds = [VelocityLedger::SEED_PREFIX, payer_agent_asset.as_ref(), &policy_id.to_le_bytes()],        bump = velocity_ledger.bump,    )]    pub velocity_ledger: Account<'info, VelocityLedger>,     #[account(
  1. Line 43 /// which itself is invoked by trusted x402 facilitators.: Uses x402, an HTTP 402 pattern where an agent pays per request with an on-chain payment.
  2. Line 44 pub caller: Signer<'info>,: Requires this account to have signed the transaction.
  3. Line 48 seeds = [PolicyAccount::SEED_PREFIX, payer_agent_asset.as_ref(), &policy_id.to_le_bytes()]: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 49 bump = policy_account.bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.

How to run, build and test

These commands come from the repo's own manifests (package.json scripts, Anchor.toml, Cargo, go.mod, Makefile). Check the README for prerequisites and environment variables.

DirectoryCommandRuns
.npm run testanchor test
.npm run lintprettier */*.js "*/**/*{.js,.ts}" --check
docs-sitenpm run devnext dev
docs-sitenpm run startnext start
docs-sitenpm run buildnext build
docs-sitenpm run linteslint
live-appnpm run devnext dev
live-appnpm run startnext start
live-appnpm run buildnext build
webnpm run devnext dev
webnpm run startnext start
webnpm run buildnext build
webnpm run linteslint
examples/attestor-demonpm run buildtsc
examples/attestor-demonpm run testts-mocha -p ./tsconfig.json -t 30000 "test/**/*.test.ts"
examples/attestor-demonpm run linttsc --noEmit

What you could build from it

Used in lessons