wane-sdk is the unified client an AI agent uses to share on-chain immune
memory. Before an agent signs, it reads the antibody registry (reading is
immunity). When it detects a novel threat, it mints an antibody so every other
agent is immune next time. For full enforcement it routes outflows through a
session wallet that screens each send on-chain and reverts a flagged transfer
before any value moves. One package covers Base (viem) and Solana
(@solana/web3.js), with the same threat taxonomy on both.
One agent gets hit. Every agent gets immune.
| Feature | EVM (Base) | Solana |
|---|---|---|
check / assertSafe before signing (free view) |
stable | stable |
Herd feed: count, recent, live watch |
stable | count |
report a novel threat (stake $WANE, mint antibody) |
stable | instruction builder |
| Per-agent policy: caps, kill switch, TTL, allowlists | stable | policy account |
| Session wallet: enroll, deposit, screened send, withdraw | vault + 7702 | vault PDA |
EIP-7702 one-signature protection (enable, send, wrap) |
stable | not applicable |
Non-custodial screening vault (createVault, vaultSend) |
stable | session vault |
| Agent session keys: scoped, capped, expiring, revocable | setVaultSession / sendAsSession |
set_session / sendAsSession |
Auto-report loop (protect: guard, run, report on attack) |
stable | manual |
| Zero-config deployment factories (no address pasting) | stable | stable |
flowchart TD
A[agent] -->|check target, free view| R[Wane antibody registry]
R -->|flagged? id?| A
A -->|report novel threat, stake + mint| R
R -->|AntibodyMinted| H[herd feed: recent / watch]
A -->|enforced path: enable / createVault| S[session wallet]
S -->|screened send| SC{on-chain screen}
SC -->|clean: value moves| D[destination]
SC -. flagged: revert Blocked .-> D
The EVM client screens on-chain two ways: EIP-7702 (the agent's own wallet
delegates to WaneDelegate, so every execute() is screened) and WaneVault
(funds live in the vault, so there is no raw-send bypass and ERC-20 recipients
decoded from calldata are screened too). The Solana client screens through a
session vault PDA that binds the destination's antibody PDA by seeds, so a
flagged send cannot be slipped through by omitting the account.
See docs/architecture.md for the full data flow and
docs/threat-model.md for what the screen does and
does not stop.
# 1. clone
git clone https://github.com/WaneProtocol/wane-sdk
cd wane-sdk
# 2. install (peer deps viem + @solana/web3.js install as devDeps here)
npm install
# 3. typecheck, test, build
npm run lint # tsc --noEmit
npm test # jest: discriminators, PDAs, address encoding
npm run build # emits dist/ with .d.tsRequired tooling:
- Node.js >= 18
- npm 9+ (or pnpm / yarn, your choice)
Peer dependencies (provided by your app): viem ^2.21 for the EVM client,
@solana/web3.js ^1.98 for the Solana client. Import only the chain you use and
the other runtime never loads.
Read before you sign, on Base:
import { Wane } from "wane-sdk";
const wane = Wane.base({ agent: myAgentAddress });
const v = await wane.checkAddress("0x1465E33f687C557BF275D6d692eC1316126d8e9e");
// { flagged: true, antibodyId: 42n, kind: 0, subject: "0x...e9e" }
await wane.assertSafe(target); // throws WaneBlockedError if flaggedDrop-in protection with one EIP-7702 signature:
import { createWalletClient, http } from "viem";
import { Wane } from "wane-sdk";
const wane = Wane.base({ agent: account.address });
const wallet = createWalletClient({ account, chain, transport: http() });
await wane.enable(wallet); // one signature, screens every send after
const tx = await wane.send(wallet, { to, value }); // reverts Blocked before value moves if flagged
// "0x<tx hash>"Read and route on Solana:
import { Wane, PublicKey } from "wane-sdk/solana";
const wane = Wane.devnet();
const flagged = await wane.checkAddress(new PublicKey("So111...112"));
// { flagged: false, antibody: null }
const sig = await wane.send(ownerSigner, destination, 1_000_000_000n);
// "<base58 signature>" ; throws if the program reverts on a flagged destinationReport a novel threat so the herd goes immune (Base):
const res = await wane.report(wallet, {
subject: evm.addressSubject(badAddress),
evidence: proofHash,
});
// { skipped: false, txHash: "0x...", id: 43n } (skipped: true if already known)The owner keeps the master key. The agent holds a separate session key that can only make screened sends within caps until it expires, and can never withdraw or change the vault. The owner can revoke it at any time.
Owner grants a scoped key (Base):
import { Wane } from "wane-sdk";
import { parseEther } from "viem";
const wane = Wane.base();
await wane.setVaultSession(ownerWallet, vault, {
key: agentAddress, // a fresh keypair the agent will hold
perTxCap: parseEther("0.001"),
expiry: BigInt(Math.floor(Date.now() / 1000) + 7 * 86400),
});
// revoke any time: await wane.revokeVaultSession(ownerWallet, vault)The agent transacts with only the session key, never the master key:
import { privateKeyToAccount } from "viem/accounts";
const session = privateKeyToAccount(process.env.WANE_SESSION_KEY);
const agentWallet = createWalletClient({ account: session, chain: base, transport: http() });
await wane.vaultSend(agentWallet, vault, { to, value });
// screened and capped: reverts if the recipient is flagged or the amount is over capSolana is the same shape: setSessionIx (owner) then
sendAsSession(session, owner, to, lamports) (agent). Full drop-in agents are in
examples/agent-base.ts and
examples/agent-solana.ts.
wane-sdk/
├── package.json unified manifest, peer deps viem + @solana/web3.js
├── tsconfig.json NodeNext, strict, declaration output
├── jest.config.mjs ts-jest ESM
├── README.md
├── LICENSE MIT
├── CONTRIBUTING.md / CODE_OF_CONDUCT.md / SECURITY.md
├── CHANGELOG.md / ROADMAP.md / CITATION.cff
├── .editorconfig / .gitattributes / .gitignore
├── .github/
│ ├── workflows/ci.yml format check + build (light, green)
│ ├── ISSUE_TEMPLATE/ bug_report.md, feature_request.md, config.yml
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── CODEOWNERS / FUNDING.yml / SUPPORT.md
├── src/
│ ├── index.ts unified entry: Wane.base() / Wane.solana(), evm + solana namespaces
│ ├── evm/ viem client (registry, policy, 7702 delegate, vault) + ABI slice
│ └── solana/ @solana/web3.js client (registry, session vault, PDAs)
├── test/
│ └── encoding.test.ts discriminators, PDA seeds, address subject encoding
├── examples/ base-check, base-protect, solana-session, agent-base, agent-solana
└── docs/ architecture, threat-model, deployments
- Base mainnet (8453): registry
0x027F371fB139A57EcD2A2E175d30157eEA1C56de, policy0x26deE4503C7f67356837ED41cE285026EF256667, delegate0x9175d735D512d730510148ED4D6702eF99CF4901, vault factory0x571Ac11310fb5d69D660C30f696a81e097Db8586, token0x1465E33f687C557BF275D6d692eC1316126d8e9e - Base Sepolia: registry
0x027F371fB139A57EcD2A2E175d30157eEA1C56de - Solana: registry
5Arj4zbFs5GigEGUSUb9hKNMYaPLqv1XgJXUcnGJ1wJH, vault5YK7gMzkjUvLaxfNisMdtjRK4UeAiJBCSonB3GgrtTYh
Full table with explorer links in docs/deployments.md.
See CONTRIBUTING.md and
CODE_OF_CONDUCT.md.
MIT. See LICENSE.
- Website: https://wane.network
- X: https://x.com/wanedotnetwork (raw handle:
@wanedotnetwork) - GitHub: https://github.com/WaneProtocol/wane-sdk
- Issues: https://github.com/WaneProtocol/wane-sdk/issues