home
source

ward&weave is two off-chain agents bound to one on-chain program. the program is a solana token-2022 deployment whose transfer fee harvests into a program-owned reserve and whose only privileged callers are the agents. on each tick the off-chain loop reads reserve and market state, the reasoning bridge returns at most one proposed move per agent, and the program clamps that move inside three invariants before it can execute: a monotonic floor that never decreases, liquidity that is locked the instant it is placed and never withdrawn, and a reserve that can never be drawn below its own floor. the off-chain process carries no authority. it proposes, the chain disposes, and if the loop dies the program holds its rules without it. below are the four files that make that true.


files
agent.ts
reason.ts
program.rs
types.ts
// ward & weave :: off-chain agent loop
// it proposes; the program disposes. no authority lives here.

import { Program } from "@coral-xyz/anchor";
import { PublicKey } from "@solana/web3.js";
import { reason } from "./reason";
import { ChainState, Move } from "./types";

const EVERY_MS = Number(process.env.TICK_MS ?? 30_000);

async function readState(program: Program, reserve: PublicKey): Promise<ChainState> {
  const acc = await program.account.reserveState.fetch(reserve);
  return {
    price:    acc.price.toNumber(),
    floor:    acc.floor.toNumber(),
    depthBid: acc.depthBid.toNumber(),
    depthAsk: acc.depthAsk.toNumber(),
    reserve:  acc.balance.toNumber(),
    flow:     acc.flowWindow.map((x: any) => x.toNumber()),
  };
}

async function submit(program: Program, m: Move): Promise<string> {
  switch (m.kind) {
    case "buy_and_lock":                 // clamp: floor only up, reserve >= floor
      return program.methods.wardBuyLock(m.quote).rpc();
    case "add_depth":                    // clamp: liquidity locked, never withdrawn
      return program.methods.weaveAddDepth(m.side, m.size).rpc();
    case "hold":
      return "skip";
  }
}

async function tick(program: Program, reserve: PublicKey): Promise<void> {
  const state = await readState(program, reserve);
  const moves = await reason(state);     // one proposed move per agent
  for (const m of moves) {
    if (m.kind === "hold") continue;
    await submit(program, m);            // the on-chain clamp is the real guard
  }
}

export async function run(program: Program, reserve: PublicKey): Promise<void> {
  for (;;) {
    try { await tick(program, reserve); }
    catch { /* log and continue. the program holds its rules without us. */ }
    await new Promise((r) => setTimeout(r, EVERY_MS));
  }
}