Mandatedocs
ReferenceSDK

Client

createMandate, createMandateFromEnv and the MandateClient surface.

npm i @yashjain99/mandate-sdk viem

The package is ESM, targets Node 22 and modern bundlers, and has viem ^2.30 as its only required peer. Everything below is exported from @yashjain99/mandate-sdk.

createMandate(config)

Returns a MandateClient. Framework-agnostic; @yashjain99/mandate-ai wraps it for the Vercel AI SDK and MCP.

Prop

Type

chains defaults to Base Sepolia and Arc testnet. Each entry is { chain: Chain, rpc?: string }; the rpc applies to reads and, with LocalAgentWallet, to sends and receipt polling too.

createMandateFromEnv(overrides?)

Node only. Builds the client from environment variables, with any MandateConfig field overridable. Resolution order:

FieldSource
accountMANDATE_ACCOUNT, then ACCOUNT, then contracts/deployments/base-sepolia.json (or MANDATE_DEPLOYMENTS_DIR)
RPCsMANDATE_RPC_<chainId>, then BASE_SEPOLIA_RPC and ARC_TESTNET_RPC
walletCIRCLE_API_KEY + CIRCLE_ENTITY_SECRET + CIRCLE_WALLET_SET_ID (all three) → CircleAgentWallet; else AGENT_PRIVATE_KEYLocalAgentWallet; else ReadOnlyAgentWallet
storeMANDATE_STORE_DIRfileStore; else memoryStore()
guardianMANDATE_GUARDIAN_KEYlocalGuardian (development only)
graphApiKeyGRAPH_API_KEY

In read-only mode positions, markets, planning, simulation and approval text all work; execute returns a clear error.

MandateClient

MemberReturnsNotes
account, wallet, store, guardianSigner?, graphApiKey?public readonly fields
chain(chainId)Chainthrows if not configured
pub(chainId)PublicClientcached per chain
chainIds()number[]
explorer(chainId, hash)stringexplorer URL for a transaction
owner()Addresscached
guardian(chainId?)Addresslive on-chain read; the first call checks every chain agrees and throws otherwise
agentAddress()Address
positions()objectbalances on both chains, Compound position (debt, collateral, health factor, liquidation price, APR), mandate caps and remaining allowance, guardian and agent
repayments(){ repayments[], currentDebtUsdc, healthFactor }intents recorded on the Arc account with daysLeft and overdue
markets(amountUsdc){ snapshot, ranked }The Graph, Morpho and the on-chain Compound twin; see Markets
plan(requests, opts)Planbuild from ActionRequest[]; opts: { id?, intent, venueId?, venueExplanation? }
simulate(plan){ results, verified, deferred, failed }progressive; see Plans and steps
execute(plan, index)StepResultidempotent, re-simulates, handles approvals
executeAll(plan, onStep?)StepResult[]stops at the first failure or guardian pause
approvals.request(plan, step)PendingApprovalbuilds and caches the text for the live nonce
approvals.submit(plan, step, signature, via?)StoredApprovalverifies against the on-chain guardian, stores
approvals.signWith(signer, plan, step, onStatus?)StoredApprovalrequest, sign with a GuardianSigner, submit
findStepTxHash(plan, step, lookbackBlocks?)Hex | undefinedrecovers a hash from StepExecuted logs

StepResult

type StepResult =
  | { ok: true; step: number; title: string; txHash?: Hex; explorer?: string; summary: string; alreadyDone?: boolean; note?: string; [k: string]: unknown }
  | { ok: false; step: number; error: string; awaitingGuardian?: boolean; approval?: PendingApproval };

alreadyDone means the chain reported the step executed in an earlier attempt and nothing was re-sent. awaitingGuardian means stop and collect a signature; approval.text is what to sign.

Helpers

  • isDone(step): done or skipped.
  • jsonSafe(value): deep-copies with bigints as decimal strings; plans are stored this way.

Subpath exports

ImportContentsEnvironment
@yashjain99/mandate-sdkeverything belowNode, bundlers
@yashjain99/mandate-sdk/ledger-webledgerWebGuardianbrowser (WebHID)
@yashjain99/mandate-sdk/store-redisredisStore, RedisLikeNode
@yashjain99/mandate-sdk/abicontract and protocol ABIsanywhere
@yashjain99/mandate-sdk/chainschains, arcTestnet, explorerTxanywhere

On this page