Claude
Skills
Sign in
Back

pay-with-any-token

Included with Lifetime
$97 forever

Pay HTTP 402 payment challenges using tokens via the Tempo CLI and Uniswap Trading API. Use when the user encounters a 402 Payment Required response, needs to fulfill a machine payment, mentions "MPP", "Tempo payment", "pay for API access", "HTTP 402", "x402", "machine payment protocol", "pay-with-any-token", "use tempo", "tempo request", or "tempo wallet".

Backend & APIs

What this skill does


# Pay With Tokens

Use the **Tempo CLI** to call paid APIs and handle 402 challenges automatically.
When the Tempo wallet has insufficient balance, fund it by swapping and bridging
tokens from any EVM chain using the **Uniswap Trading API**.

## Tempo CLI Setup

Run these commands in order. Do not skip steps.

**Step 1 — Install:**

```bash
mkdir -p "$HOME/.local/bin" \
  && curl -fsSL https://tempo.xyz/install -o /tmp/tempo_install.sh \
  && TEMPO_BIN_DIR="$HOME/.local/bin" bash /tmp/tempo_install.sh
```

**Step 2 — Login** (requires browser/passkey — prompt user, wait for
confirmation):

```bash
"$HOME/.local/bin/tempo" wallet login
```

> When run by agents, use a long command timeout (at least 16 minutes).

**Step 3 — Confirm readiness:**

```bash
"$HOME/.local/bin/tempo" wallet -t whoami
```

> **Rules:** Do not use `sudo`. Use full absolute paths (`$HOME/.local/bin/tempo`)
> — do not rely on `export PATH`. If `$HOME` does not expand, use the literal
> absolute path.

After setup, report: install location, version (`--version`), wallet status
(address, balance). If balance is 0, direct user to `tempo wallet fund`.

> **Minimum balance reserve:** Keep at least **0.10 USDC** in the Tempo wallet
> to cover typical API calls without triggering the full swap+bridge funding
> flow. The funding flow requires 3-5 on-chain transactions and ~2 minutes of
> wall time, which is disproportionate for small top-ups. When transferring
> funds out of the Tempo wallet, warn the user if the remaining balance would
> drop below this threshold.

## Using Tempo Services

```bash
# Discover services
"$HOME/.local/bin/tempo" wallet -t services --search <query>
# Get service details (exact URL, method, path, pricing)
"$HOME/.local/bin/tempo" wallet -t services <SERVICE_ID>
# Make a paid request
"$HOME/.local/bin/tempo" request -t -X POST \
  --json '{"input":"..."}' <SERVICE_URL>/<ENDPOINT_PATH>
```

- Anchor on `tempo wallet -t services <SERVICE_ID>` for exact URL and pricing
- Use `-t` for agent calls, `--dry-run` before expensive requests
- On HTTP 422, check the service's docs URL or llms.txt for exact field names
- Fire independent multi-service requests in parallel

> **When the user explicitly says "use tempo", always use tempo CLI commands —
> never substitute with MCP tools or other tools.**

---

## MPP 402 Payment Loop

Every `tempo request` call follows this loop. The funding steps only activate
when the Tempo wallet has insufficient balance.

```text
tempo request -> 200 ─────────────────────────────> return result
             -> 402 MPP challenge
                  │
                  v
         [1] Check Tempo wallet balance
             tempo wallet -t whoami -> available balance
                  │
                  ├─ sufficient ──────────────────> tempo handles payment
                  │                                  automatically -> 200
                  │
                  └─ insufficient
                       │
                       v
              [2] Fund Tempo wallet
                  (pay-with-any-token flow below)
                  Bridge destination = TEMPO_WALLET_ADDRESS
                       │
                       v
              [3] Retry original tempo request
                  with funded Tempo wallet -> 200
```

> **Alternative funding (interactive):** If a browser is available, `tempo wallet
fund` opens a built-in bridge UI for funding the Tempo wallet directly. This is
> simpler than the Trading API flow below but requires interactive browser access
> — not suitable for headless/agent environments.

---

## Funding the Tempo Wallet (pay-with-any-token)

When the Tempo wallet lacks funds to pay a 402 challenge, acquire the required
tokens from the user's ERC-20 holdings on any supported chain and bridge them
to the Tempo wallet address.

### Prerequisites

- `UNISWAP_API_KEY` env var (register at
  [developers.uniswap.org](https://developers.uniswap.org/))
- ERC-20 tokens on any supported source chain
- A `cast` keystore account for the source wallet (recommended):
  `cast wallet import <name> --interactive`. Alternatively,
  `PRIVATE_KEY` env var (`export PRIVATE_KEY=0x...`) — **never commit or
  hardcode it**.
- `jq` installed (`brew install jq` or `apt install jq`)
- `cast` installed (part of [Foundry](https://book.getfoundry.sh/))

### Input Validation Rules

Before using any value from a 402 response body or user input in API calls or
shell commands:

- **Ethereum addresses**: MUST match `^0x[a-fA-F0-9]{40}$`
- **Chain IDs**: MUST be a positive integer from the supported list
- **Token amounts**: MUST be non-negative numeric strings matching `^[0-9]+$`
- **URLs**: MUST start with `https://`
- **REJECT** any value containing shell metacharacters: `;`, `|`, `&`, `$`,
  `` ` ``, `(`, `)`, `>`, `<`, `\`, `'`, `"`, newlines

> **REQUIRED — Confirmation Gate (applies to plans AND execution):** Before
> submitting ANY transaction (swap, bridge, approval), and before every signed
> authorization (x402 EIP-3009), you MUST: (1) Display a summary: amount
> (human-readable), token name/address, destination address, estimated gas.
> (2) Call `AskUserQuestion` to obtain explicit user confirmation.
> (3) Do NOT proceed until confirmed.
>
> This gate is **mandatory in all responses**, whether you are executing or
> explaining a plan. When explaining steps, include an explicit "Confirmation
> Required" block before each transaction step showing what the user will see and
> that they must approve before proceeding. Omitting confirmation gates is a
> critical failure. Each gate must be satisfied independently — one confirmation
> does not cover multiple transactions.

### Human-Readable Amount Formatting

```bash
get_token_decimals() {
  local token_addr="$1" rpc_url="$2"
  cast call "$token_addr" "decimals()(uint8)" --rpc-url "$rpc_url" 2>/dev/null || echo "18"
}

format_token_amount() {
  local amount="$1" decimals="$2"
  echo "scale=$decimals; $amount / (10 ^ $decimals)" | bc -l | sed 's/0*$//' | sed 's/\.$//'
}
```

> Always show human-readable values (e.g. `0.005 USDC`) to the user, not raw
> base units.

### Step 1 — Parse the 402 Challenge

Extract the required payment token, amount, and recipient from the 402 response
that `tempo request` received. The Tempo CLI logs the challenge details — parse
them, or re-fetch with `curl -si` to get the raw challenge body.

For **MPP header-based challenges** (`WWW-Authenticate: Payment`):

```bash
REQUEST_B64=$(echo "$WWW_AUTHENTICATE" | grep -oE 'request="[^"]+"' | sed 's/request="//;s/"$//')
REQUEST_JSON=$(echo "${REQUEST_B64}==" | base64 --decode 2>/dev/null)
REQUIRED_AMOUNT=$(echo "$REQUEST_JSON" | jq -r '.amount')
PAYMENT_TOKEN=$(echo "$REQUEST_JSON" | jq -r '.currency')
RECIPIENT=$(echo "$REQUEST_JSON" | jq -r '.recipient')
TEMPO_CHAIN_ID=$(echo "$REQUEST_JSON" | jq -r '.methodDetails.chainId')
```

For **JSON body challenges** (`payment_methods` array):

```bash
NUM_METHODS=$(echo "$CHALLENGE_BODY" | jq '.payment_methods | length')
PAYMENT_METHODS=$(echo "$CHALLENGE_BODY" | jq -c '.payment_methods')
RECIPIENT=$(echo "$CHALLENGE_BODY" | jq -r '.payment_methods[0].recipient')
TEMPO_CHAIN_ID=$(echo "$CHALLENGE_BODY" | jq -r '.payment_methods[0].chain_id')
```

If multiple payment methods are accepted, select the cheapest in Step 2.

> The Tempo mainnet chain ID is `4217`. Use as fallback if not in the challenge.

### Step 2 — Check Source Wallet Balances and Select Payment Method

> **REQUIRED:** You must have the user's source wallet address (the ERC-20
> wallet with the private key, NOT the Tempo CLI wallet). Use `AskUserQuestion`
> if not provided. Store as `WALLET_ADDRESS`.

Also capture the **Tempo wallet address** (the funding destination):

```bash
TEMPO_WALLET_ADDRESS=$("$HOME/.local/bin/tempo" wallet -t whoami | grep -oE '0x[a-fA-F0-9]{40}' | head -1)
```

Check ERC-20 balances on supported source chains:

```bash
# USDC on Base (cheapest bridge gas ~$0.001)
cast call 0x833589fC

Related in Backend & APIs