Launch dashboard

ARCANUM / FIELD MANUAL 01

Govern the wallet.
Then let it move.

A practical guide to deploying an agent wallet on Arc, writing the doctrine that constrains it, and taking the first restraint without guesswork.

READING TIME / 08 MIN

For workspace operators. Assumes an Arc testnet wallet and a signed SIWE session.

00 / READ THIS FIRST

A governed wallet is a boundary, not a bank account.

The agent proposes a transaction. ARCANUM evaluates the proposal against a signed policy doctrine. Only the governed wallet can settle it, and every verdict becomes a ledger record. The model never receives the operator key.

01

Agent proposes

A typed spend intent enters the policy surface.

02

Policy decides

Caps, destinations, and velocity are checked.

03

Human intervenes

Exceptions pause until quorum is satisfied.

01 / DEPLOY A GOVERNED WALLET

Start with a wallet that cannot improvise.

Create the wallet from the operator console, then bind the first doctrine before funding it. Use Arc testnet for the complete rehearsal: the same signing ceremony, a safe balance.

  1. 1

    Connect the operator

    Open the console with your EOA and complete Sign-In with Ethereum (SIWE). The message includes your workspace domain, Arc testnet, a nonce, and an expiry. Never paste a private key into an agent runtime.

  2. 2

    Name the boundary

    Register the wallet as procurement-bot and record 0x3f…9a2c in the inventory. The wallet address is the stable identity used in every ledger decision.

  3. 3

    Fund the rehearsal

    Send a small USDC balance on Arc testnet. Confirm the chain ID and token contract in the wallet drawer before your first proposal.

TERMINAL
arcana wallet inspect \
  --wallet 0x3f...9a2c \
  --network arc-testnet

02 / AUTHOR A POLICY DOCTRINE

Write the exception before the request.

A doctrine is executable policy with an accountable author. Keep it narrow: name approved vendors, set a transaction cap, and describe what happens when the facts fall outside the line.

DOCTRINE / PROCUREMENT-BOTv4.18 · DRAFT
when
vendor in [ AWS, OpenAI ]
and amount $500

then
ALLOW · record to ledger
otherwise
ESCALATE · require 2 operators
daily cap $5,000 · USDC only · expires 30d

Publish only after a second operator reviews the rendered rule. A doctrine change is a new signed instrument; it does not rewrite previous ledger decisions.

03 / HANDLE YOUR FIRST RESTRAINT

A pause is a successful control.

When growth-bot asks Anthropic for $2,100.00, the request should stop. Review the reason, compare it to the doctrine, then make a recorded decision. Speed is not the objective; legibility is.

Open restraint queue

04 / OPERATOR RUNBOOK

Keep the record useful.

01Review pending restraints at the start of every shift.
02Rotate doctrines when vendors, caps, or agent responsibilities change.
03Treat an anomaly as a question, not a verdict.
04Leave the ledger with a clear answer: allowed, blocked, or human-decided.

05 / SDK QUICKSTART

Deploy your first GuardedWallet.

Stand up a governed agent wallet on Arc Testnet in five steps. Every transaction it attempts will be evaluated against a Doctrine before it can settle on-chain.

  1. 1

    Install the SDK

    Add the Arcanum SDK to your project. It ships with the ArcanumClient, typed contract ABIs, and every verdict type.

  2. 2

    Configure the signer

    Point the client at Arc Testnet and supply an admin signer that will own the Doctrine.

  3. 3

    Deploy the wallet with a Doctrine

    Create a GuardedWallet through WalletFactory and attach spend limits, category caps, and an escalation quorum.

  4. 4

    Fund the wallet

    Transfer test USDC to the deployed address; it appears in the AGENT REGISTER immediately.

  5. 5

    Watch the Event Stream

    Every attempted transaction now flows through the governed event stream with a verdict.

TERMINAL / bash
npm install arcanum-sdk viem

Snippets are files, not terminal commands. Save the block below as test.mjs, then run node test.mjs. It reads a live GuardedWallet on Arc Testnet: real policy, real verdicts, no keys required.

test.mjs / run: node test.mjs
import { ArcanumClient } from "arcanum-sdk";
import { defineChain, formatUnits, parseUnits } from "viem";

const arcTestnet = defineChain({
  id: 5042002,
  name: "Arc Testnet",
  nativeCurrency: { name: "USDC", symbol: "USDC", decimals: 6 },
  rpcUrls: { default: { http: ["https://arc-testnet.drpc.org"] } },
});

// A live GuardedWallet on Arc Testnet. Swap in your own after you deploy it.
const client = new ArcanumClient({
  walletAddress: "0x34Ce73E82d48bF377597D8A3c80f9a6DF2085EFa",
  chain: arcTestnet,
  rpcUrl: "https://arc-testnet.drpc.org",
});

const policy = await client.getPolicy();
console.log("Per-tx cap:", formatUnits(policy.perTxCap, 6), "USDC");

const allowed = await client.simulate({
  to: "0xF45C70f2b08397419b11751041c0D9547CcEDEaD", // allowlisted vendor
  amount: parseUnits("1", 6),
});
console.log("Allowlisted vendor:", allowed.verdict);

const denied = await client.simulate({
  to: "0xB1a111A87A454977F5fB2c02F547D0f346e23Ca8", // unknown vendor
  amount: parseUnits("1", 6),
});
console.log("Unknown vendor:", denied.verdict, denied.reason ?? "");

Ready to deploy your own? Save this as deploy.mjs, set OPERATOR_KEY to a funded Arc Testnet key, and run it.

deploy.mjs / run: node deploy.mjs
import { WalletFactoryAbi } from "arcanum-sdk";
import { createWalletClient, defineChain, http, parseUnits } from "viem";
import { privateKeyToAccount } from "viem/accounts";

const arcTestnet = defineChain({
  id: 5042002,
  name: "Arc Testnet",
  nativeCurrency: { name: "USDC", symbol: "USDC", decimals: 6 },
  rpcUrls: { default: { http: ["https://arc-testnet.drpc.org"] } },
});

// The operator account that owns the Doctrine. Gas on Arc is paid in USDC.
const account = privateKeyToAccount(process.env.OPERATOR_KEY);
const walletClient = createWalletClient({ account, chain: arcTestnet, transport: http() });

// WalletFactory on Arc Testnet
const WALLET_FACTORY = "0x51A560589e23AcD2e57173641267f4583e0e65E7";

const policy = {
  perTxCap: parseUnits("50", 6),
  daily24hCap: parseUnits("500", 6),
  monthlyRollingCap: parseUnits("5000", 6),
  allowedCategories: 0b11111n,
  escalationThreshold: parseUnits("100", 6),
  requireAllowlist: true,
};

const agentSigner = "0xYourAgentSignerAddress"; // your AI agent's signing address
const council = [account.address]; // escalation approvers

const txHash = await walletClient.writeContract({
  address: WALLET_FACTORY,
  abi: WalletFactoryAbi,
  functionName: "createWallet",
  args: [account.address, "ResearchAgent", policy, [agentSigner], council, 1],
});
console.log("Deployed:", txHash);
RESTRAINT

On-chain policy changes affect real testnet state. Test with small limits first.

WARNING

A quorum of 1 disables multi-party approval. Use at least 2 for treasury wallets.

INFO

USDC token amounts are expressed in 6-decimal base units. One dollar is parseUnits("1", 6).