Examples

Practical flows for using Cortex as a merchant, agent operator, or application developer. Reads can use the hosted Base Sepolia API; writes go through your wallet, RPC, and the deployed contracts.

Base Sepolia Setup

export API_URL=https://cortex-api.projectaegis.ai
export RPC_URL=https://sepolia.base.org
export COMMERCE_REGISTRY_ADDRESS=0xc4c014d9eb2d07ff6f7d2b8625e8cf3bc1150574
export AGENT_REGISTRY_ADDRESS=0x39e3a043532187af2ffe308154375fb662ccb0d6
export POLICY_MODULE_ADDRESS=0x7120d45cbd6b5d079f39418e4f84880c634ef614
export INTENT_BOOK_ADDRESS=0x16f7e7c4856bad4dcbE61400630087Dab75B229E
ContractAddress
CommerceRegistry0xc4c014d9eb2d07ff6f7d2b8625e8cf3bc1150574
AgentRegistry0x39e3a043532187af2ffe308154375fb662ccb0d6
PolicyModule0x7120d45cbd6b5d079f39418e4f84880c634ef614
IntentBook0x16f7e7c4856bad4dcbE61400630087Dab75B229E

Add Yourself as a Merchant

Publish merchant metadata offchain, hash it, then anchor the merchant record onchain.

{
  "name": "Example Data Merchant",
  "website": "https://merchant.example",
  "support": "support@merchant.example",
  "payout_chain": "base-sepolia",
  "refund_policy": "Refunds available when fulfillment does not match accepted quote terms."
}
export MERCHANT_KEY=0x...
export PAYOUT_ADDRESS=0x...
export MERCHANT_METADATA_URI=ipfs://merchant-metadata
export MERCHANT_METADATA_HASH=0x...

cast send "$COMMERCE_REGISTRY_ADDRESS" \
  "registerMerchant(address,string,bytes32)" \
  "$PAYOUT_ADDRESS" \
  "$MERCHANT_METADATA_URI" \
  "$MERCHANT_METADATA_HASH" \
  --rpc-url "$RPC_URL" \
  --private-key "$MERCHANT_KEY"

curl "$API_URL/merchants?owner=0x..."

Register a Service

A service is a merchant-owned capability with a metadata URI/hash and capability hash.

export MERCHANT_ID=1
export SERVICE_ID=enrich-company-v1
export SERVICE_METADATA_URI=ipfs://service-metadata
export SERVICE_METADATA_HASH=0x...
export CAPABILITY_HASH=0x...

cast send "$COMMERCE_REGISTRY_ADDRESS" \
  "registerService(uint256,string,string,bytes32,bytes32)" \
  "$MERCHANT_ID" \
  "$SERVICE_ID" \
  "$SERVICE_METADATA_URI" \
  "$SERVICE_METADATA_HASH" \
  "$CAPABILITY_HASH" \
  --rpc-url "$RPC_URL" \
  --private-key "$MERCHANT_KEY"

curl "$API_URL/services?merchant_id=$MERCHANT_ID&active=true"

Register an Agent

export AGENT_KEY=0x...
export AGENT_METADATA_URI=ipfs://agent-metadata
export AGENT_PUBKEY=0xaabb
export AGENT_CAPABILITIES_HASH=0x0000000000000000000000000000000000000000000000000000000000000001

cast send "$AGENT_REGISTRY_ADDRESS" \
  "registerAgent(string,bytes,bytes32)" \
  "$AGENT_METADATA_URI" \
  "$AGENT_PUBKEY" \
  "$AGENT_CAPABILITIES_HASH" \
  --rpc-url "$RPC_URL" \
  --private-key "$AGENT_KEY"

curl "$API_URL/agents/1"

Create a Policy Smart Account

In the current repo, PolicyAccount is deployed with an agent signer and the shared policy module. A production app should wrap this in its account factory, bundler, and wallet UX.

const policyAccountHash = await walletClient.deployContract({
  abi: PolicyAccountABI,
  bytecode: policyAccountBytecode,
  args: [agentOwnerAddress, POLICY_MODULE_ADDRESS],
});

const receipt = await publicClient.waitForTransactionReceipt({ hash: policyAccountHash });
const policyAccount = receipt.contractAddress;

await walletClient.writeContract({
  address: policyAccount,
  abi: PolicyAccountABI,
  functionName: "setSpendLimit",
  args: [USDC_ADDRESS, 100_000_000n],
});

await walletClient.writeContract({
  address: policyAccount,
  abi: PolicyAccountABI,
  functionName: "setTargetAllowed",
  args: [merchantOrRouterAddress, true],
});

Allow Facilitator or x402 Payments

export MERCHANT_OWNER=0x...
export TOKEN=0x...
export FACILITATOR=0x...
export MAX_PER_PAYMENT=1000000
export MAX_PER_DAY=10000000

cast send "$POLICY_MODULE_ADDRESS" \
  "setPaymentPolicy(address,address,address,uint256,uint256,bool)" \
  "$MERCHANT_OWNER" \
  "$TOKEN" \
  "$FACILITATOR" \
  "$MAX_PER_PAYMENT" \
  "$MAX_PER_DAY" \
  true \
  --rpc-url "$RPC_URL" \
  --private-key "$AGENT_KEY"

Commit a Quote

Quotes bind payment rail, amount, expiry, nonce, resource hash, terms hash, optional x402 payload hash, and zero-fee protocol instrumentation.

const quote = {
  merchantId: 1n,
  serviceNumericId: 1n,
  agent: agentAddress,
  token: USDC_ADDRESS,
  facilitator: facilitatorAddress,
  amount: 1_000_000n,
  paymentRail: 3, // 0=transfer, 1=swap, 2=facilitator, 3=x402
  expiresAt: BigInt(Math.floor(Date.now() / 1000) + 3600),
  paymentNonce: 1n,
  resourceHash,
  termsHash,
  x402PayloadHash,
};

const quoteHash = await publicClient.readContract({
  address: COMMERCE_REGISTRY_ADDRESS,
  abi: CommerceRegistryABI,
  functionName: "computeQuoteHash",
  args: [
    quote.merchantId,
    quote.serviceNumericId,
    quote.agent,
    quote.token,
    quote.facilitator,
    quote.amount,
    quote.paymentRail,
    quote.expiresAt,
    quote.paymentNonce,
    quote.resourceHash,
    quote.termsHash,
    quote.x402PayloadHash,
  ],
});

await walletClient.writeContract({
  address: COMMERCE_REGISTRY_ADDRESS,
  abi: CommerceRegistryABI,
  functionName: "commitQuote",
  args: [quote],
});

Record a Receipt and Fulfillment

await facilitatorWallet.writeContract({
  address: COMMERCE_REGISTRY_ADDRESS,
  abi: CommerceRegistryABI,
  functionName: "recordReceipt",
  args: [quoteHash, resultHash],
});

await merchantWallet.writeContract({
  address: COMMERCE_REGISTRY_ADDRESS,
  abi: CommerceRegistryABI,
  functionName: "recordFulfillment",
  args: [receiptId, fulfillmentHash],
});
curl "$API_URL/receipts?agent=0x..."
curl "$API_URL/merchants/1/reputation"

Submit an Agent Intent with the SDK

import { AgentChainClient } from "@cortex/sdk";

const client = new AgentChainClient({
  apiUrl: "https://cortex-api.projectaegis.ai",
  publicClient,
  walletClient,
  intentBookAddress: INTENT_BOOK_ADDRESS,
  chain: { id: 84532 },
});

const result = await client.createIntent({
  intent: {
    inputToken: USDC_ADDRESS,
    outputToken: OUTPUT_TOKEN,
    nonce: BigInt(Date.now()),
    constraints: {
      amountInMax: 1_000_000n,
      amountOutMin: 990_000n,
      deadline: BigInt(Math.floor(Date.now() / 1000) + 1800),
      slippageBps: 100,
    },
  },
  metadata: {
    metadata_uri: "ipfs://intent-metadata",
    execution_target: routerAddress,
    execution_data: "0x...",
  },
  preflight: {
    account: policyAccountAddress,
    target: routerAddress,
    value: "0",
    data: "0x...",
  },
});

const bids = await client.listBids(result.intentId, "open");

Agent Runtime Checklist

  1. Fetch merchant and service state from the API.
  2. Verify service metadata hashes against fetched metadata documents.
  3. Check trust signals, disputes, and merchant reputation.
  4. Confirm quote hash matches local payment/resource/terms payloads.
  5. For x402, verify x402PayloadHash against the facilitator payment requirement.
  6. Run policy preflight for target calls or signed payment policy.
  7. Submit payment or intent.
  8. Wait for receipt and fulfillment indexing.
  9. Record a dispute or trust signal if fulfillment is invalid.

Run the Full Demo

make e2e

# Testnet demo with funded wallets
cp ops/.env.testnet ops/.env.deployed
cd ops/demo
npm run build
node dist/run.js