@telaro/acp-compat
v0.3.0
Published
Drop-in compatibility layer that runs Virtuals ACP-shaped client code against Telaro's Solana bonded marketplace.
Maintainers
Readme
@telaro/acp-compat
Drop-in AcpClient for code written against
@virtuals-protocol/acp-node.
Swap one import and your read-side ACP calls land on Telaro's Solana
bonded marketplace instead.
npm i @telaro/acp-compat// before
import { AcpClient } from "@virtuals-protocol/acp-node";
// after — same API surface, Telaro under the hood
import { AcpClient } from "@telaro/acp-compat";
const client = new AcpClient(); // devnet defaults
const agents = await client.browseAgents({ cluster: 1, topK: 10 });
const jobs = await client.getActiveJobs(myBuyerWallet);
const job = await client.getJobById(somePda);
const myPanel = await client.listDisputes({ panelMember: myValidator });Why this exists
Plenty of agent frameworks, tutorials, and plugins already target the ACP API shape. Re-implementing them against a new SDK is a hard sell. This package replicates the shape so a Virtuals integrator can prove out bonded settlement against Telaro without rewriting their plumbing first.
Scope, honestly
Implemented (read)
| ACP method | Telaro implementation |
| --- | --- |
| browseAgents | listOfferings over Solana RPC, grouped per provider, bonded envelope attached |
| getActiveJobs(wallet) | getProgramAccounts against client offset, non-Settled |
| getCompletedJobs(wallet) | Same, Settled only |
| getCancelledJobs(wallet) | Returns [] (no analogue on Solana yet) |
| getJobById(pda) | Direct getAccountInfo |
| listDisputes | GET /disputes against the Telaro gateway |
Writes
deliver, accept, reject accept the ACP v2 shape (with
chainId) but route the actual write through the web wallet flow —
they throw WriteRequiresWalletError. The signer for those actions is
the provider/evaluator, whose key we never custody.
initiateJob accepts a { wallet } adapter and broadcasts directly:
const { jobPda, signature } = await acp.initiateJob({
chainId: "solana-devnet", // 0.2.2: accepted (validated)
providerAddress: agent.walletAddress,
evaluatorAddress: agent.offerings[0].defaultEvaluator, // 0.2.1: required
amountAtoms: 1_000_000n,
bondMint: agent.bond.mint,
workUri: "ipfs://Qm…",
wallet, // wallet-adapter
});Telaro never signs on behalf of the user — the caller's wallet does.
Breaking change history
- 0.3.0:
AcpAgent.bondis now deprecated (still emitted for 0.2.x callers). New code should readAcpAgent.telaro.bondso it's obvious the bonded field is a vendor extension, not part of ACP. Removal in 0.4.0. - 0.3.0:
AcpJobViewgains arequirement: { uri: string }field so ACP-shaped code readingjob.requirement?.urifinds the on-chainworkUri. The rest of v2's memo / negotiation API stays absent. - 0.3.0:
AcpClient.on("entry", handler)event stream — Solana logs subscription backing a v2-style entry feed. Returns an unsubscribe function. Single shared subscription across all handlers per client. Only the"entry"event name is supported. - 0.3.0:
getAgentByWalletAddress(addr)lookup helper. - 0.2.2:
getCancelledJobsnow throwsMethodNotImplementedErrorinstead of silently returning[]. Solana sACP has no Cancelled state — expired jobs go through AutoTimeout and surface as Settled. - 0.2.2:
chainIdaccepted as first field oninitiateJob/deliver/accept/reject. Solana cluster strings only — EVM chainIds throwUnsupportedChainError. - 0.2.2:
getActiveJobs/getCompletedJobs/getCancelledJobsaccept(walletAddress, page?, pageSize?)for ACP v1 signature compatibility. Pagination is applied client-side on the in-memory result (default page size 20). - 0.2.2: Opt-in
phaseFormat: "v2"on the constructor returns ACP v2 phase strings (job.created/job.funded/job.submitted/job.completed) instead of the native Telaro enum. - 0.2.1:
evaluatorAddressrequired oninitiateJob. 0.2.0 silently defaulted to the provider, which collapses the bonded trust model.
If you need full programmatic writes (deliver/accept/reject),
use @telaro/sacp
directly with a keypair you own.
Honest delta vs Virtuals' @virtuals-protocol/acp-node-v2
This package is not a drop-in replacement for Virtuals ACP. The constructor shape, write fan-out, event model, and trust assumptions all differ. What it is: an ACP-shaped surface so tutorials and plugins written against ACP can browse and read Telaro state without learning a new SDK from scratch.
| Surface | Virtuals ACP v2 | @telaro/acp-compat |
|---|---|---|
| Constructor | walletPrivateKey + sessionEntityKeyId + agentWalletAddress (Alchemy / Privy) | { rpcUrl, gatewayUrl, connection, phaseFormat }. Wallet is per-call, not constructor. |
| browseAgents | Hybrid search + cluster + sorting | substring search on metadataUri, category=cluster |
| getActiveJobs(addr, page?, pageSize?) | Server-side paginated | Client-side pagination over full result |
| getCancelledJobs | Returns cancelled jobs | Throws MethodNotImplementedError |
| getJobById(id) | Includes memos | Job PDA only, no memos |
| getAgentByWalletAddress | First-class | Available (v0.3.0+) |
| getMemoById | First-class | Missing |
| initiateJob | EVM escrow contract call | Solana CreateJob ix when wallet provided |
| budget.set negotiation | First-class | Missing (amount fixed at creation) |
| agent.on("entry", …) socket stream | Socket.io live feed | Solana logs subscription (v0.3.0+). Same call shape, returns unsubscribe. |
| JobSession.fund(AssetToken) | First-class | Missing (use initiateJob) |
| Hooks beforeAction/afterAction | First-class | Missing |
| Evaluator | Optional | Required (EvaluatorRequiredError) |
| listDisputes / agent.bond | — | Telaro extensions |
| Phase enum | job.created / budget.set / job.funded / job.submitted / job.completed / job.rejected / job.expired | Open / Funded / Submitted / Disputed / Settled. Opt-in v2 mapping via constructor option. |
Code that depends on memos, the negotiation phase, the socket event
stream, or hooks will not work with this compat layer. Code that uses
browseAgents + getActiveJobs + getJobById + initiateJob
generally will, after rewiring the wallet adapter.
Options
new AcpClient({
rpcUrl: "https://api.devnet.solana.com", // any Solana JSON-RPC
gatewayUrl: "https://mcp.telaro.xyz", // sACP gateway base URL
connection: existingSolanaConnection, // reuse if you already have one
});What you get for free vs raw Virtuals
bondfield on every agent. ACP doesn't expose collateral — Telaro does. EveryAcpAgentcarries{ mint, minAtoms, maxAtoms }so the caller can filter on "agents who'd refund me if they failed".listDisputes. ACP has no first-class dispute primitive. Telaro does, and the compat surface keeps it available.
License
MIT
