> ## Documentation Index
> Fetch the complete documentation index at: https://docs.altheia.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Chain reads

> Read the live policy, vault balances, and audit log straight from chain. Decode policy aborts.

These functions read state directly from chain. No backend dependency: the policy object and the audit events are the source of truth.

## `readPolicyObject`

```ts theme={null}
readPolicyObject(client, policyId): Promise<PolicyObject>
```

Reads the live multi-asset policy — the authoritative caps, allowed actions, scope, expiry, and state.

```ts theme={null}
type PolicyObject = {
  caps: { coinType: string; perTxCap: string; perDayCap: string; spentToday: string }[];
  actions: number[];
  allowedPackages: string[];
  expiresAtMs: string;
  revoked: boolean;
  paused: boolean;
};
```

`readPolicy(client, policyId)` returns a flatter `PolicySnapshot` (single budget asset) with `agentId`, `perTxCap`, `perDayCap`, `spentToday`, `allowedPackages`, `expiresAtMs`, `revoked`, `paused`, `version`.

## `vaultBalances`

```ts theme={null}
vaultBalances(client, vaultId): Promise<{ coinType: string; amount: string }[]>
```

Every coin balance the multi-asset vault holds. Balances live in dynamic fields keyed by coin type; this enumerates them and reads each amount. Returns `[]` if the vault has no assets.

## `readAuditLog`

```ts theme={null}
readAuditLog(client, corePkg, limit = 50): Promise<AuditEvent[]>
```

The on-chain activity log: `AllowedAction`, `WithdrawalAttested`, `PolicyRevoked`, `PolicyUpdated` events emitted by `corePkg`, in descending order.

```ts theme={null}
type AuditEvent = { type: string; txDigest: string; timestampMs: string | null; data: unknown };
```

## `decodePolicyAbort`

```ts theme={null}
decodePolicyAbort(err): { code: number; reason_code: string; message: string } | null
```

Extracts a policy `MoveAbort` from a thrown error or a `devInspect` failure status, and maps the abort code to a stable reason. Only aborts raised by the `policy` module are decoded; returns `null` for any other failure (so you can tell a policy denial apart from a liquidity or gas failure).

```ts theme={null}
try {
  await agent.swap(2_000_000_000n);
} catch (e) {
  const ab = decodePolicyAbort(e);
  if (ab) console.log(ab.reason_code, ab.message); // "over_per_tx_cap", "over per-tx cap"
  else throw e;                                    // not a policy decision
}
```

| Code | `reason_code`           |
| ---- | ----------------------- |
| 1    | `policy_revoked`        |
| 2    | `policy_expired`        |
| 3    | `agent_paused`          |
| 4    | `over_per_tx_cap`       |
| 5    | `over_per_day_cap`      |
| 6    | `package_not_allowed`   |
| 7    | `wrong_policy`          |
| 8    | `action_not_allowed`    |
| 9    | `action_config_missing` |
| 10   | `asset_not_allowed`     |

<Card title="guardedSubmit" icon="arrow-right" href="/sdk/guarded-submit" horizontal>
  Dry-run, record a denial without spending gas, and submit only when allowed.
</Card>
