A job is written by Solidity contracts and read by everyone else. The contracts emit events; what actually lands on chain is a topic hash and a run of thirty-two-byte words, ABI-encoded, saying nothing on their own. Nobody can act on that, and a single job is spread across more than one contract and more than one standard.
The SDK is the translation layer between the two. It pins each event signature (JobCreated(uint256,address,address,address,uint256,address) and the rest), re-derives every topic hash from that signature in tests so a typo cannot silently mismatch live traffic, and folds the decoded events into one job: what was agreed, what stage it is at, who it is waiting on, whether the worker has a record worth trusting, and what a settlement would look like.
It reads and drives Moonbeam Protocol, and it signs nothing: it never holds a key, it prepares each call, and the partner's own signer sends it.
npm install @moonbeam-foundation/sdk npx moonbeam demo
Version 0.5.3on npm. The demo needs no key and no network: it replays the covered job from its three Base transactions, re-derives the equation job's grade from Jev's recorded answers and matches it to the decision recorded on Base, then settles the covered job on it.
Each row is a source the SDK decodes, and what it turns into.
| SOURCE | WHAT IT CARRIES | WHAT THE SDK TURNS IT INTO |
|---|---|---|
| ERC-8183 events | the job lifecycle: create, fund, submit, settle | one job state, order-insensitive, with contradictions surfaced rather than swallowed |
| ERC-8004 registries | agent identity and reputation | who the parties are, who owns them now, and what others have claimed about them |
| ACP job ledger | the live agent-commerce tape on Base | the same job shape, decoded from a second ledger by the same code |
| Moonbeam’s job contract | a covered job’s price, premium, deposit and cover | the terms settle() works through for each of the four endings |
Every ledger that speaks the standard is decoded by one set of pinned signatures.
What comes out the other end is one receipt: who the parties were, what was agreed, what was delivered, how it was graded and where the money went. Outcomes are computed from the evidence and the deadline, never submitted by either party.
Your own indexer subscribes to the logs; the SDK publishes the watch list and decodes what you feed it. Reading down follows one job from the first log to settlement.
erc8183.eventForTopic() / erc8183.stateAfter()READING LOGSerc8004.eventForTopic()READING LOGSfoldTask() / foldTasks()BUILDING A JOBerc8183.settlementModeOf()BUILDING A JOBrecourseFor() / waitingOn()TRACKING A JOBendingFromTrail()TRACKING A JOBmeasureCoverage()CHECKING THE READsettle()SETTLING UPprepareSettlement()SETTLING UPThe grader runs from @moonbeam-foundation/sdk/judge, stage by stage: evidence, facts, Jev's answers, the verdict, the record and the ending call. Jev is called with your own TypeSafe key, from console.typesafe.ai.
jobFacts()gradeJob()recordGrade()endJob()verifyGrade()The layer underneath can discover an agent and settle a job, but it has no way for two agents that have never met to agree a price: a buyer names a worker and funds the job directly. The SDK adds the missing step.
Every bid is validated when it is made, against the same rules settlement will later apply. A bid that could not settle is rejected with a reason while the buyer still has other options, rather than accepted and discovered once money is locked.
The flow is four calls: a buyer opens an intent, anyone bids, the best bid is accepted into terms, and those same terms settle. A bid that could not settle is refused when it is made, by name, so a mispriced offer never reaches a queue.
Every refusal works like that one: named, pointing at the object that caused it, and actionable without asking anybody. They are part of the contract rather than error strings to be logged and forgotten.