Skip to main content

Policy Simulator

The PolicySimulator evaluates transactions against policies locally, without deploying anything on-chain or interacting with Lit Protocol. It’s designed for testing and development.

Usage

import { PolicySimulator } from "@policykit/sdk";
import { parseEther } from "viem";

const simulator = new PolicySimulator();

const report = await simulator.evaluate(policy, {
  target: "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
  value: parseEther("0.5"),
  data: "0x38ed1739...",
});

console.log(report.allowed);      // true
console.log(report.results);      // Per-rule results
console.log(report.failedRules);  // Only failed rules

Constructor

new PolicySimulator(options?: SimulatorOptions)

Options

OptionTypeDefaultDescription
verbosebooleanfalseLog detailed evaluation steps
mockTimestampnumberDate.now()Override current timestamp (for testing cooldowns/windows)
mockStateMockState{}Pre-populate state for Tier 2 rules

MockState

interface MockState {
  spendHistory?: {
    token: Address;
    amount: bigint;
    timestamp: number;
  }[];
  lastTransactionTimestamp?: number;
}

Methods

evaluate(policy, txParams)

Evaluate a transaction against all rules in a policy.
const report = await simulator.evaluate(policy, {
  target: "0x...",
  value: parseEther("1"),
  data: "0x...",
});
ParameterTypeDescription
policyPolicyThe policy to evaluate
txParamsTxParamsTransaction parameters
Returns: Promise<EvaluationReport> The simulator evaluates all tiers:
  • Tier 1: Fully simulated (exact match with on-chain behavior)
  • Tier 2: Simulated with mock state
  • Tier 3: Best-effort simulation (slippage checks use provided data, simulation rule always passes)

evaluateRule(rule, txParams)

Evaluate a single rule against transaction parameters.
const result = await simulator.evaluateRule(
  { type: "MAX_VALUE", params: { maxValue: parseEther("1") } },
  { target: "0x...", value: parseEther("2"), data: "0x" }
);

console.log(result.passed); // false
console.log(result.reason); // "Value 2000000000000000000 exceeds max 1000000000000000000"
ParameterTypeDescription
ruleOnChainRule | OffChainRuleThe rule to evaluate
txParamsTxParamsTransaction parameters
Returns: Promise<RuleResult>

reset()

Reset the simulator’s internal state (spend tracking, cooldown timestamps).
simulator.reset();

Examples

Testing Spend Limits

const simulator = new PolicySimulator({
  mockState: {
    spendHistory: [
      {
        token: "0xUSDC",
        amount: parseUnits("40000", 6), // Already spent 40k
        timestamp: Date.now() / 1000 - 3600, // 1 hour ago
      },
    ],
  },
});

const policy = new PolicyBuilder("test")
  .spendLimit("0xUSDC", parseUnits("50000", 6), 86400)
  .build();

// This should fail — 40k + 15k = 55k > 50k limit
const report = await simulator.evaluate(policy, {
  target: "0xUSDC",
  value: 0n,
  data: encodeTransfer("0xRecipient", parseUnits("15000", 6)),
});

console.log(report.allowed); // false

Testing Cooldowns

const simulator = new PolicySimulator({
  mockTimestamp: 1700000000,
  mockState: {
    lastTransactionTimestamp: 1699999800, // 200 seconds ago
  },
});

const policy = new PolicyBuilder("test")
  .cooldown(300) // 5 minutes
  .build();

const report = await simulator.evaluate(policy, txParams);
console.log(report.allowed); // false — only 200s since last tx
The simulator is designed for development and testing. Tier 3 rules are evaluated on a best-effort basis since the full Lit Protocol environment is not available locally.