Sol.College

Full lesson

agentbond

What it does

From the project README:

[](https://solana.com) [](https://explorer.solana.com/address/5foUTphb99ztvEknWcEc5fNhvUsGx77pUiSsJi36d1L3?cluster=devnet) [](https://arena.colosseum.org/hackathon) [](LICENSE)
Original
DiveshK007/agentbond
SuperStack fork
Blockchains/agentbond @ c958d9f
Stars
0
Last push (original)
2026-06-26
Languages
TypeScript, Rust, CSS, JavaScript, Shell
Detected stack
@solana/kitAnchorMetaplexNext.jsweb3.js
Categories
AI & Agents
Licence
MIT
Homepage
https://agentbond-three.vercel.app

Architecture

124 source files. By extension: .ts ×63, .tsx ×50, .rs ×11.

Top-level directorySource files
app57
api17
agent_bond16
elizaos-plugin9
sdk9
bots8
scripts6
mcp2

On-chain programs: agent_bond/programs/agent_bond

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/agentbond/. 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.

DiveshK007/agentbond · agent_bond/programs/agent_bond/src/instructions/resolution.rs L13–36 @ c958d9f · MIT · original
        mut,        seeds = [b"job", job.job_index.to_le_bytes().as_ref()],        bump = job.bump,        constraint = job.status == 1 @ AgentBondError::JobNotAssigned,        constraint = job.agent == agent_owner.key() @ AgentBondError::NotAssignedAgent,    )]    pub job: Account<'info, Job>,     #[account(mut)]    pub agent_owner: Signer<'info>,} pub fn submit_result(ctx: Context<SubmitResult>, result_hash: [u8; 32]) -> Result<()> {    let clock = Clock::get()?;    require!(        clock.unix_timestamp <= ctx.accounts.job.deadline,        AgentBondError::DeadlinePassed    );     ctx.accounts.job.result_hash = result_hash;    ctx.accounts.job.status = 2;     emit!(events::ResultSubmitted {        job_index: ctx.accounts.job.job_index,
  1. Line 14 seeds = [b"job", job.job_index.to_le_bytes().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  2. Line 15 bump = job.bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  3. Line 22 pub agent_owner: Signer<'info>,: Requires this account to have signed the transaction.
  4. Line 26 let clock = Clock::get()?;: Reads on-chain time from the Clock sysvar.
  5. Line 27 require!(: An explicit validation that aborts the instruction with an error.
  6. Line 35 emit!(events::ResultSubmitted {: Emits an Anchor event that clients can parse from the logs.
DiveshK007/agentbond · agent_bond/programs/agent_bond/src/instructions/job.rs L217–240 @ c958d9f · MIT · original
     #[account(        seeds = [b"bid", job.key().as_ref(), agent_pubkey.as_ref()],        bump = bid.bump,    )]    pub bid: Account<'info, Bid>,     #[account(mut)]    pub poster: Signer<'info>,     pub system_program: Program<'info, System>,} pub fn assign_agent(ctx: Context<AssignAgent>, agent_pubkey: Pubkey) -> Result<()> {    let clock = Clock::get()?;     let reward = ctx.accounts.job.reward;    let agent_stake = ctx.accounts.agent_profile.stake;    let collateral = reward.min(agent_stake / 10);     ctx.accounts.agent_profile.locked_stake = ctx.accounts.agent_profile.locked_stake        .checked_add(collateral).ok_or(AgentBondError::Overflow)?;     let job = &mut ctx.accounts.job;
  1. Line 219 seeds = [b"bid", job.key().as_ref(), agent_pubkey.as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  2. Line 220 bump = bid.bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  3. Line 225 pub poster: Signer<'info>,: Requires this account to have signed the transaction.
  4. Line 231 let clock = Clock::get()?;: Reads on-chain time from the Clock sysvar.
  5. Line 234 let agent_stake = ctx.accounts.agent_profile.stake;: Touches staking state: the amount locked and when it was locked.
  6. Line 238 .checked_add(collateral).ok_or(AgentBondError::Overflow)?;: Uses checked arithmetic so overflow fails instead of wrapping.
DiveshK007/agentbond · agent_bond/programs/agent_bond/src/instructions/admin.rs L13–35 @ c958d9f · MIT · original
        seeds = [b"protocol"],        bump = protocol_config.bump,        constraint = protocol_config.admin == admin.key() @ AgentBondError::NotAdmin,    )]    pub protocol_config: Account<'info, ProtocolConfig>,     #[account(mut)]    pub admin: Signer<'info>,} pub fn update_fee(ctx: Context<UpdateFee>, new_fee_bps: u16) -> Result<()> {    require!(new_fee_bps <= 1000, AgentBondError::InvalidFeeBps);     let old = ctx.accounts.protocol_config.platform_fee_bps;    ctx.accounts.protocol_config.platform_fee_bps = new_fee_bps;     emit!(events::FeeUpdated {        old_fee_bps: old,        new_fee_bps,    });     Ok(())}
  1. Line 13 seeds = [b"protocol"],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  2. Line 14 bump = protocol_config.bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  3. Line 20 pub admin: Signer<'info>,: Requires this account to have signed the transaction.
  4. Line 24 require!(new_fee_bps <= 1000, AgentBondError::InvalidFeeBps);: An explicit validation that aborts the instruction with an error.
  5. Line 29 emit!(events::FeeUpdated {: Emits an Anchor event that clients can parse from the logs.
DiveshK007/agentbond · agent_bond/programs/agent_bond/src/instructions/agent.rs L73–96 @ c958d9f · MIT · original
    profile.status = 0;    profile.bump = ctx.bumps.agent_profile;     system_program::transfer(        CpiContext::new(            ctx.accounts.system_program.to_account_info(),            system_program::Transfer {                from: ctx.accounts.owner.to_account_info(),                to: ctx.accounts.stake_vault.to_account_info(),            },        ),        stake_amount,    )?;     ctx.accounts.protocol_config.total_agents = ctx.accounts.protocol_config.total_agents        .checked_add(1).ok_or(AgentBondError::Overflow)?;     emit!(events::AgentRegistered {        owner: ctx.accounts.owner.key(),        name: name_bytes,        stake: stake_amount,    });     Ok(())
  1. Line 74 profile.bump = ctx.bumps.agent_profile;: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  2. Line 77 CpiContext::new(: Makes a cross-program invocation into another program.
  3. Line 88 .checked_add(1).ok_or(AgentBondError::Overflow)?;: Uses checked arithmetic so overflow fails instead of wrapping.
  4. Line 90 emit!(events::AgentRegistered {: Emits an Anchor event that clients can parse from the logs.
  5. Line 93 stake: stake_amount,: Touches staking state: the amount locked and when it was locked.

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
elizaos-pluginnpm run devtsc --watch
elizaos-pluginnpm run buildtsc
agent_bondnpm run lintprettier */*.js "*/**/*{.js,.ts}" --check
apinpm run devts-node server.ts
apinpm run startts-node server.ts
mcpnpm run devts-node src/server.ts
mcpnpm run startnode dist/server.js
mcpnpm run buildtsc
sdknpm run devtsc --watch
sdknpm run buildtsc
appnpm run devnext dev
appnpm run startnext start
appnpm run buildnext build
appnpm run linteslint
agent_bondanchor buildcompile programs and generate IDLs
agent_bondanchor testlocal validator + test suite

What you could build from it

Used in lessons