# Anchora x402 Agent Instruction

Use this file as the single public instruction entrypoint for agents that need to fetch Anchora RWA data and pay per request through x402.

Public URL:

```text
https://anchora.markets/anchora-x402-agent.md
```

Use the public helper repository for all shell-based setup and payment commands. Do not require access to the private Anchora app repository.

```text
https://github.com/Marakaya/anchora-x402-agent
```

## Wallet Public Key Only Fast Path

If the current task is only to create or show an Anchora x402 wallet public key, do not read beyond this section. Do not fetch catalog/quote, do not inspect any Anchora project repo, and do not run both wallet reuse and wallet creation.

Use exactly one wallet command:

- If the user did not explicitly ask for a fresh isolated wallet, reuse/create `default`:

```bash
cd "$HOME/.codex/anchora-x402-agent" 2>/dev/null \
  && node -p "require('./package.json').version" \
  && (test -d node_modules/@solana/kit || npm ci) \
  && npm --silent run x402:wallet:ensure
```

If this fails because `$HOME/.codex/anchora-x402-agent` is missing, continue to **Option B: Public Anchora Helper Workspace** below, install the helper once into that stable path, then rerun only this command.

- If the user explicitly asks for a fresh/new/isolated wallet, skip `ensure` and create one fresh wallet directly:

```bash
cd "$HOME/.codex/anchora-x402-agent" \
  && npm --silent run x402:wallet -- create --wallet "fresh-$(date +%Y%m%d%H%M%S)" --domain anchora.markets --per-request-usdc 0.30 --daily-usdc 1
```

If this fails because `$HOME/.codex/anchora-x402-agent` is missing, continue to **Option B: Public Anchora Helper Workspace** below, install the helper once into that stable path, then rerun only this command.

An existing `default` wallet with `spentToday: 0.3 USDC` and `dailyCap: 1 USDC` still has enough capacity for another `0.30 USDC` proof-package call; do not create a second wallet unless the user requested it. Return only the public funding address and no secret fields.

## Version Guard

Before executing payments, use helper version `0.4.5` or newer from the public repo above. If a local helper workspace already reports version `0.4.5` or newer, do not fetch, pull, clone, or reinstall just to create a wallet. Refresh only when the version is too old, the helper command fails, or the user explicitly asks for the newest helper. Older copies may fetch the protected route directly, try to redeem before settlement in bridges that intercept HTTP `402`, fall back to manual REPL signing in read-only sandboxes, split happy-path payment into slow catalog/dry-run/execute loops, clone the helper into both temp and stable directories, or spend time inspecting the private Anchora repo for a payment-only task. The current flow uses `/api/x402/v1/quote` first, includes a bridge-safe facilitator-settle path, supports filesystem-free in-memory signing, has an idempotent wallet ensure command, and has a strict fast path for agent payments.

For browser-based review with a judge/developer login, the live app also exposes:

- `https://app.anchora.markets/developer/playground` for quote-only x402 checks
- `https://app.anchora.markets/developer/logs` for API request logs
- `https://app.anchora.markets/developer/receipts` for attributed x402 settlement receipts
- `https://app.anchora.markets/developer/errors` for the API/x402 error dictionary
- `https://app.anchora.markets/developer/agent-skill` for the public helper repo and copy-paste prompt

## What Anchora Provides

Anchora returns machine-readable trust data for tokenized real-world assets:

- proof packages
- asset scores
- mint-to-asset lookup
- attestation transaction verification

Current production-facing x402 settlement is handled by Anchora through the settlement mode declared in `GET /catalog`. Anchora may use Coinbase CDP or its own direct Solana settlement mode; agents do not need Coinbase credentials. In a transparent HTTP client, call Anchora, receive a quote, sign a Solana USDC payment through a bounded signer, retry the same Anchora URL with `X-PAYMENT`, and preserve `X-PAYMENT-RESPONSE` as the receipt. In a bridge that intercepts `402`, use the helper's returned `facilitatorSettle` body first, then redeem the same target URL with the same `X-PAYMENT`.

The current public testing contour is devnet-first. Always trust the live `GET /catalog` response for the active Solana RPC/mint policy. At the moment, Anchora quotes Solana Devnet USDC (`4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU`) for x402 testing.

For hackathon or judge testing, use devnet only. Do not ask the user to fund mainnet wallets; any mainnet transaction links are historical proof artifacts, not the public test path.

## Payment-Only Fast Path

If the user asks to buy or fetch Anchora data through x402, treat it as a payment-only task. Do not inspect the private Anchora app repository, Graphify files, project memory, README, source code, migrations, or unrelated docs. Do not web-search for Anchora instructions after this instruction has been loaded. If this instruction or local skill is already loaded, do not fetch this instruction URL again. The public helper repo, `/catalog`, `/quote`, and `/api/x402/solana-rpc?method=signing-context` are sufficient.

Allowed discovery before payment only when setting up the helper, debugging, or producing an explicit audit log:

- confirm the helper workspace version with `node -p "require('./package.json').version"` when already in the helper repo
- fetch `GET /catalog`
- fetch `GET /quote`
- check wallet balance or signing context

After the user has funded the wallet and already authorized the local policy, do not run a separate catalog command or dry-run quote validation. Execute the single proof command; it performs catalog and quote validation internally before signing.

Only inspect helper source or project code after two consecutive failures from the same helper command or an undocumented response shape from Anchora. Never use Node REPL to create or sign a wallet while `create-in-memory` or `sign-x402-stdin` is available. If filesystem writes fail, switch directly to `create-in-memory`; do not try `.anchora`, `mktemp`, and then REPL in sequence.

Target timing:

- already funded wallet: one helper command that performs catalog/quote/sign/settle/redeem internally
- new wallet: show public key, wait for user funding, then one payment pass
- hostile bridge/no-direct-network: use `/quote`, one signing-context request, `--bridge-sign-stdin` or `ANCHORA_X402_BRIDGE_SIGN_INPUT_B64`, facilitator-settle, status check, redeem

Fastest happy path after the wallet exists, is funded, and the user has authorized the local policy:

```bash
npm run x402:proof -- --asset-address <asset_pda> --agent-wallet default --execute-payment --print-body --json
```

The helper validates `/catalog` and `/quote` before signing. Do not run separate catalog and dry-run commands first unless the user asked for an audit log, the wallet policy has not been authorized, or the single command fails.

Fastest wallet setup path:

1. Use an existing helper workspace if one is already present.
2. Otherwise use `$HOME/.codex/anchora-x402-agent` as the stable workspace.
3. Do not clone into a temp directory and then clone again into a stable directory.
4. Do not run `git pull`, `git fetch`, or read this public instruction URL when the existing helper version is already `0.4.5` or newer.
5. Run `npm ci` only when `node_modules/@solana/kit` is missing or after the helper repo actually changed. Do not check `node_modules/.bin/tsx`; this helper does not depend on `tsx`.
6. Create or reuse the wallet with one command:

```bash
npm run x402:wallet:ensure
```

This command creates `default` when missing and reuses it when the existing wallet already matches the Anchora policy. Do not generate timestamped wallet names unless the user explicitly requests a fresh isolated wallet. Do not wrap wallet creation in custom zsh code; `status` is a read-only zsh variable.

## Safety Rules

- Do not ask the user for a seed phrase, raw private key, or existing keypair JSON.
- Do not ask the user to run terminal commands if you have shell access. Run setup, wallet, balance, and payment commands yourself. Avoid separate catalog or dry-run commands in the funded happy path.
- Ask the user only for:
  - the Asset PDA address
  - funding the generated public key
  - payment authorization if they have not already approved a bounded policy
- The helper must validate `/catalog` and quote internally before signing.
- Refuse payment if the helper reports domain, resource URL, recipient, token mint, network, or amount mismatch with local policy.
- Never parse the `402` challenge JSON and assemble the `X-PAYMENT` header yourself. Header construction is the helper's job: it serializes the signed payload, sets the correct encoding, and links the `payment-identifier`.
- The only legitimate manual use of helper output is to transmit the produced `X-PAYMENT` header verbatim, including in the restricted-env bridge fallback where the helper emits the header and you forward it through the bridge once.
- Never edit, mutate, or reuse an `X-PAYMENT` header across attempts. If the paid retry returns an error, do not modify the header. Follow the Troubleshooting recovery procedure below.

## Canonical API

Base URL:

```text
https://anchora.markets/api/x402/v1
```

Free catalog:

```text
GET /catalog
GET /quote?route=proof-package&asset_address={asset_address}&policy=collateral_screening
GET /payments/{payment_identifier}/status
```

Paid endpoints:

```text
GET /assets/{asset_address}/proof-package?policy=collateral_screening
GET /assets/{asset_address}/score
GET /assets/by-mint/{mint}
GET /verify/{tx_signature}
```

Use the Asset PDA address in `{asset_address}` when available. Do not use a display label when an on-chain address is known.

Reference demo asset PDA:

```text
2eZLs5ZK1X7nvi835xbDxhGtUCvssV5s8WDUJF28gKvX
```

## Payment Policy

Accept only quotes with:

- `scheme: "exact"`
- `network` equal to the live `GET /catalog` settlement network (`solana-devnet` for current judge/devnet testing)
- `asset` equal to the live `GET /catalog` settlement mint / route payment asset
- `payTo` equal to the live `GET /catalog` settlement payTo
- `resource` exactly under `https://anchora.markets/api/x402/v1/`
- `maxAmountRequired` at or below the user policy cap

Recommended local wallet policy:

- per request cap: `0.30 USDC`
- daily cap: `1 USDC`

Agent proof snapshot currently costs `0.30 USDC`.

## Preferred Agent UX

Do not give the user terminal instructions. The normal conversation should look like this:

1. Tell the user: "I will create a dedicated low-balance Solana wallet for Anchora x402 payments."
2. Create the wallet yourself if you have shell plus Node/npm.
3. Show the user only the generated public key.
4. Ask the user to fund it with about `1 devnet test USDC` and `0.01 devnet SOL`.
5. Ask for the Asset PDA address if not already provided.
6. After the user confirms funding and authorizes the policy, run the single proof command.
7. Return the Anchora response and cite the settlement transaction.

## Execution Options

### Option A: Existing x402/Solana Payment Tool

If your runtime already has an x402 Solana payment tool or wallet capability:

1. Fetch `GET /catalog`.
2. Stop if `settlement.ready` is not `true`; report `settlement.detail`.
3. Prefer `GET /quote` for bridge-safe quote discovery.
4. If `/quote` is unavailable, call the paid endpoint without `X-PAYMENT` and validate the `402` quote.
5. Create a fresh `payment-identifier`.
6. Ask the bounded signer/tool to create `X-PAYMENT`.
7. Retry the exact same URL with `X-PAYMENT`.
8. Return the JSON body and preserve `X-PAYMENT-RESPONSE.transaction`.

### Option B: Public Anchora Helper Workspace

If your runtime has shell and Node/npm, but no built-in x402 payment tool, use the public Anchora x402 helper repo. Git is not required.

Public repo:

```text
https://github.com/Marakaya/anchora-x402-agent
```

First check the stable local workspace:

```bash
cd "$HOME/.codex/anchora-x402-agent" 2>/dev/null \
  && node -p "require('./package.json').version"
```

If this prints `0.4.5` or newer, stay there. Do not fetch, pull, clone, reinstall dependencies, or read this instruction URL again for wallet-only setup.

If the stable workspace is missing or too old, obtain the helper into that stable workspace by any available method:

```bash
workspace="$HOME/.codex/anchora-x402-agent"
mkdir -p "$(dirname "$workspace")"
rm -rf "$workspace"

if command -v git >/dev/null 2>&1 \
  && git clone --depth 1 https://github.com/Marakaya/anchora-x402-agent "$workspace"; then
  :
elif npm exec --yes degit@latest -- Marakaya/anchora-x402-agent "$workspace"; then
  :
elif command -v curl >/dev/null 2>&1 && command -v tar >/dev/null 2>&1; then
  mkdir -p "$workspace"
  curl -fsSL https://codeload.github.com/Marakaya/anchora-x402-agent/tar.gz/refs/heads/main \
    | tar -xz --strip-components=1 -C "$workspace"
else
  echo "Cannot download anchora-x402-agent without git, npm/degit, or curl+tar."
  exit 1
fi

cd "$workspace"
test -d node_modules/@solana/kit || npm ci
```

Optional audit-only catalog check:

```bash
npm run x402:agent -- --route catalog
```

Optional pay.sh smoke against the live devnet x402 route:

```bash
npm exec --yes --package=@solana/pay -- pay --verbose curl 'https://anchora.markets/api/x402/v1/assets/2eZLs5ZK1X7nvi835xbDxhGtUCvssV5s8WDUJF28gKvX/proof-package?policy=collateral_screening'
```

Create a limited local wallet:

```bash
npm run x402:wallet:ensure
```

If no filesystem location is writable, use in-memory mode instead of trying temp directories or writing Node REPL code manually:

```bash
npm run x402:wallet -- create-in-memory --domain anchora.markets --per-request-usdc 0.30 --daily-usdc 1
```

This prints a generated low-balance `walletRecord` that contains a secret key. Keep it inside the agent runtime only, do not show it to the user, and use it only for the authorized Anchora x402 policy. After funding the printed public key, sign a saved `signerRequest` without touching the filesystem:

```bash
npm run x402:wallet -- sign-x402-stdin < inline-wallet-sign-request.json
```

`inline-wallet-sign-request.json` shape:

```json
{
  "walletRecord": { "...": "walletRecord from create-in-memory" },
  "signerRequest": { "...": "signerRequest from offline-context-plan" }
}
```

For bridge/no-direct-network proof-package payment, prefer the runner's combined bridge signing entrypoint instead of `offline-context-plan`, `/dev/fd`, heredocs, `node -e`, or Node REPL:

```bash
printf '%s' "$BRIDGE_SIGN_INPUT_JSON" \
  | npm run x402:agent -- --bridge-sign-stdin --asset-address <asset_pda> --payment-identifier <same_payment_identifier> --json
```

If stdin, heredocs, or temporary files are unavailable, base64-encode the same JSON and use:

```bash
ANCHORA_X402_BRIDGE_SIGN_INPUT_B64="$BRIDGE_SIGN_INPUT_B64" \
  npm run x402:agent -- --bridge-sign-env --asset-address <asset_pda> --payment-identifier <same_payment_identifier> --json
```

`BRIDGE_SIGN_INPUT_JSON` shape:

```json
{
  "walletRecord": { "...": "walletRecord from create-in-memory" },
  "quoteBody": { "...": "200 JSON body from /api/x402/v1/quote" },
  "solanaContext": { "...": "JSON body from /api/x402/solana-rpc?method=signing-context&payer=<public_key>" },
  "paymentIdentifier": "anchora_YYYYMMDD_..."
}
```

The command returns the `X-PAYMENT` header, `facilitatorSettle.body`, `paymentStatus.url`, and updated secret-bearing `walletRecord` in one result. Keep the updated walletRecord inside the agent runtime only.

Show the user the printed public key. Ask them to fund that public key with:

```text
1 test USDC + 0.01 devnet SOL
```

Check balance:

```bash
npm run x402:wallet -- balance --wallet default
```

Preferred single-call payment command:

```bash
npm run x402:proof -- --asset-address <asset_pda> --agent-wallet default --execute-payment --print-body --json
```

Prefer the single-call form once the user has authorized the bounded policy. The helper validates the quote against policy before signing. Splitting into separate validate and execute steps doubles agent reasoning roundtrips and is the biggest source of slow end-to-end timings.

Equivalent fallback if your helper copy does not have the `x402:proof` script:

```bash
npm run x402:agent -- --asset-address <asset_pda> --agent-wallet default --execute-payment --print-body --json
```

Validate quote without payment:

```bash
npm run x402:agent -- --asset-address <asset_pda> --agent-wallet default
```

Use this only for explicit audit/review mode or when the user has not authorized the bounded policy. Do not run it before the single-call payment command in the funded happy path.

Execute payment only after policy authorization if you need the legacy non-JSON output:

```bash
npm run x402:agent -- --asset-address <asset_pda> --agent-wallet default --execute-payment --print-body
```

The local wallet refuses wrong domain, wrong path, wrong Solana USDC mint, wrong recipient, over-cap amount, over daily cap, and missing `payment-identifier`. If `GET /catalog` declares a devnet mint, create/fund the wallet on devnet.

### No-direct-network fallback

If your shell can access the local wallet file but cannot resolve `anchora.markets` or `api.devnet.solana.com`, keep the dedicated Anchora wallet as payer and use your HTTP bridge only as transport:

1. Fetch `/catalog` through the bridge.
2. Fetch `/quote` through the bridge and save the `200` JSON body as `quote.json`. Example:

```text
GET https://anchora.markets/api/x402/v1/quote?route=proof-package&asset_address=<asset_pda>&policy=collateral_screening
```

3. If the bridge can fetch `/quote`, do not fetch the protected route without `X-PAYMENT`. Some bridges intercept HTTP `402` and swallow the quote body.
4. If `/quote` is unavailable, fetch the target route without `X-PAYMENT` through a transparent HTTP client only, then save the `402` JSON body as `quote.json`.
5. Fetch signing context once through the bridge, immediately before signing:

```text
GET https://anchora.markets/api/x402/solana-rpc?method=signing-context&payer=<agent_wallet_public_key>
```

6. Run the combined bridge signer with `{ walletRecord, quoteBody, solanaContext, paymentIdentifier }` through `--bridge-sign-stdin` or `ANCHORA_X402_BRIDGE_SIGN_INPUT_B64`. Do not use `/dev/fd`, heredocs, temporary files, `node -e`, or Node REPL unless this helper command itself fails twice.

Legacy file-based fallback if the combined signer is unavailable:

```bash
npm run x402:agent -- --offline-context-plan --quote-file quote.json --asset-address <asset_pda> --agent-wallet default
```

7. Save the returned `signerRequest` as `signer-request.json`.
8. Run:

```bash
npm run x402:wallet -- context-plan --wallet default < signer-request.json
```

9. Prefer the returned `fetchContextWithBridge.url`. Fetch that one URL through the bridge immediately before signing and save the response as `solana-context.json`.

If your environment cannot use the one-call context URL, fetch every `fetchWithBridge[].url` through the bridge instead. Fetch `latestBlockhash` last, immediately before signing. Save `solana-context.json` as:

```json
{
  "latestBlockhash": { "...": "paste latestBlockhash response object" },
  "accounts": {
    "<account-address>": { "...": "paste non-null account response object" }
  }
}
```

10. Sign locally with the same `paymentIdentifier` from the offline context plan:

```bash
npm run x402:agent -- --offline-sign --quote-file quote.json --solana-context-file solana-context.json --asset-address <asset_pda> --agent-wallet default --payment-identifier <same_payment_identifier>
```

11. If your bridge is transparent to `402`, retry the exact target URL through the bridge with the returned `X-PAYMENT` header.
12. If your bridge intercepts `402`, POST the helper's returned `facilitatorSettle.body` to `facilitatorSettle.url`, then check `paymentStatus.url` until `status: "settled"`, then GET the target URL with the same `X-PAYMENT` header to redeem the response.

Do not pay through the bridge wallet. The bridge is only the HTTP/RPC transport; the local Anchora wallet signs the x402 payment.

Do not run a separate facilitator pre-verify in restricted bridge mode. It can consume enough time for the blockhash to expire. If the facilitator-settle or paid retry reports a structured `blockhash_expired` error with `retryable: true` and no `checkTransaction`, refresh `solana-context.json`, re-run the offline signing command once with the same `paymentIdentifier`, and retry immediately.

### Bridge intercepts HTTP 402

Some agent runtimes and payment bridges treat HTTP `402` as their own protocol signal. If you see an error like `402 Payment Required but no recognized protocol`, the bridge is intercepting the protected-route challenge before you can read it.

Use `/quote` instead of the protected route for quote discovery:

```text
GET /api/x402/v1/quote?route=proof-package&asset_address=<asset_pda>&policy=collateral_screening
```

Then sign locally with the dedicated Anchora wallet. Do not try the protected URL first through that bridge. Instead:

1. POST the helper's `facilitatorSettle.body` to `https://anchora.markets/api/x402/facilitator/settle`.
2. GET `https://anchora.markets/api/x402/v1/payments/<paymentIdentifier>/status` until it returns `status: "settled"`.
3. GET the original protected URL with the same helper-produced `X-PAYMENT` header to redeem the response.

Do not pay with the bridge wallet. The protected URL recognizes the pre-settled facilitator attempt and caches the response without submitting the Solana transaction a second time.

Facilitator-settle technical failures intentionally do not use HTTP `402`; they return structured `409` JSON so x402-aware bridges do not swallow the body. If you still see `402 Payment Required but no recognized protocol` from facilitator-settle, refresh the helper/skill first.

## Troubleshooting

### Recovery protocol

Anchora is idempotent on `payment-identifier`: duplicate submissions with the same identifier can return `X-PAYMENT-RESPONSE.cached: true` without double-charging. However, a new payment attempt is safe only when one of these is true:

1. The helper or server error says the failure happened before settlement was accepted, with `errorReason: "blockhash_expired"` or `error: "blockhash_expired"`, `retryable: true`, and no `checkTransaction`.
2. You independently verify that the original transaction did not settle by polling the `checkTransaction` signature, if present, against a public Solana RPC until it expires.

If neither condition holds, do not create a new payment. The original transaction may still settle.

### `blockhash_expired` with `retryable: true`

The transaction expired before broadcast or before Anchora accepted it. This is safe to retry once with a fresh signing context and the same `payment-identifier` only when `checkTransaction` is empty.

### `settlement_pending` with HTTP 409 and `checkTransaction`

Anchora broadcast the transaction but did not see confirmation within its wait window. Do not re-sign or repay. Poll `checkTransaction`. If it confirms, use the same signature as the settlement receipt and wait for Anchora status/reconciliation to expose cached access. If it expires, retry with a fresh signing context.

You can check Anchora's server-side status for a known identifier:

```bash
npm run x402:agent -- --check-payment <payment_identifier>
```

### `invalid_x_payment` with HTTP 400

The header failed to deserialize. The official helper should not produce this. It usually means manual header tampering or a helper bug. Rerun the helper command; do not edit the header.

### Generic HTTP error without structured `error`

The server phase is unknown. Do not auto-retry. Surface the error and check payment status before creating a new payment.

Expected direct-network timing is 10-30 seconds with an already funded wallet. First-time wallet creation adds only the user funding wait. Restricted bridge fallback can take 60-180 seconds by design. If a direct-network flow exceeds 2 minutes after funding, use the single `npm run x402:proof -- ... --execute-payment --print-body --json` command instead of separate catalog/dry-run/execute calls.

### Option C: No Shell Or No Node/npm

If you do not have shell access or a local Node/npm runtime:

- you can read `GET /catalog`
- you can explain the x402 flow
- you cannot create a local agent wallet or execute payment autonomously in this environment

Be honest with the user and ask them to switch to an agent environment with shell and Node/npm access, or provide a bounded signer capability.

## Manual x402 Flow

1. Fetch `/catalog`.
2. Stop if `settlement.ready` is not `true`; report `settlement.detail`.
3. Prefer `GET /quote?...` to receive the same `accepts[0]` as `200 JSON`.
4. If `/quote` is unavailable and your HTTP client is transparent to `402`, call the target route without `X-PAYMENT`.
5. Validate quote against policy, including the live catalog `network`.
6. Generate a fresh `payment-identifier`.
7. Ask signer/tool to create an `X-PAYMENT` header.
8. Retry the exact same URL with `X-PAYMENT`.
9. Return JSON body and preserve `X-PAYMENT-RESPONSE.transaction`.
10. If `X-PAYMENT-RESPONSE.cached` is `true`, tell the user this was an idempotent retry, not a new charge.

## Response Guidance

For proof-package responses, summarize:

- asset name and asset PDA address
- score or confidence
- underwriting policy profile
- automation readiness
- recommended action
- warnings, blockers, or risk issues
- signature/integrity status
- settlement transaction from `X-PAYMENT-RESPONSE`

For the default demo asset, `automationReadiness: "blocked"` with `recommendedAction: "route_to_manual_review"` is expected. The sample asset intentionally uses several attestor wallets under one demo company so reviewers can test the full lifecycle quickly. Treat this as concentration-risk detection working correctly, not as payment or proof-package failure.

Do not invent missing evidence. If Anchora returns an error, report it and stop.
