Build on Mandate
Mandate is a standalone NEAR contract, not a feature baked into one app. Hire a Swarm gates every job's budget through the exact same two calls below — your app can too, instead of writing its own spend-limit logic from scratch.
Quickstart
Contract IDs for this live testnet deployment.
NEXT_PUBLIC_NEAR_NETWORK=testnetNEXT_PUBLIC_MANDATE_CONTRACT_ID=mandate-f70187.testnetNEXT_PUBLIC_TASK_MARKET_CONTRACT_ID=market-f70187.testnetThe pattern
Mandate never calls into your contract, and your contract never has to know Mandate exists at the type level — the caller just does both calls in sequence. If the first one panics, the second never runs.
1. authorize_spend(mandate_id, your_contract_id, amount) // fails closed2. your_contract.your_method(...) // only reached if 1 succeededTypeScript — near-api-js
The exact pattern agents/src/coordinator.ts uses.
await account.functionCall({ contractId: MANDATE_CONTRACT_ID, methodName: "authorize_spend", args: { id: mandateId, target: yourContractId, amount: amountYocto }, gas: 30_000_000_000_000n,});// only reached if authorize_spend didn't throwawait account.functionCall({ contractId: yourContractId, methodName: "yourMethod", args: { /* ... */ }, gas: 30_000_000_000_000n, attachedDeposit: BigInt(amountYocto),});near-cli
For scripting, testing, or a quick manual check against a deployed mandate.
$near call $MANDATE_CONTRACT_ID authorize_spend \$ '{"id": 0, "target": "'$YOUR_CONTRACT_ID'", "amount": "1000000000000000000000000"}' \$ --accountId $AGENT_ACCOUNT$ $near view $MANDATE_CONTRACT_ID get_mandate '{"id": 0}'Mandate contract reference
Who else is already building on it
contracts/task-market (Hire a Swarm) gates every job's budget through Mandate using only the pattern above — it never imports or calls into Mandate beyond that one authorize_spend call. That decoupling is the point: your app can be the second.