# Pay With App

> >

- **Type:** Skill
- **Install:** `agentstack add skill-uniswap-uniswap-ai-pay-with-app`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Uniswap](https://agentstack.voostack.com/s/uniswap)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Uniswap](https://github.com/Uniswap)
- **Source:** https://github.com/Uniswap/uniswap-ai/tree/main/packages/plugins/uniswap-trading/skills/pay-with-app
- **Website:** https://developers.uniswap.org

## Install

```sh
agentstack add skill-uniswap-uniswap-ai-pay-with-app
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Pay With APP (OKX Agent Payments Protocol on X Layer)

Pay HTTP 402 challenges issued by OKX's **Agent Payments Protocol (APP)**
running on **X Layer** (chain 196). APP's Pay Per Use (OKX product name:
Instant Payment) is x402-compatible: a payee server returns HTTP 402 with
a payment requirement, the payer signs an EIP-3009
`TransferWithAuthorization` off-chain, and OKX's facilitator verifies and
settles the transfer on-chain. Settlement is zero-gas to the payer on X
Layer.

This skill handles the full happy path:

1. Detect a 402 challenge whose network resolves to X Layer (chain 196)
2. Verify the payer wallet has the requested asset (typically USDT0)
3. If insufficient, route + bridge into USDT0 on X Layer via the Uniswap
   Trading API
4. Sign the EIP-3009 authorization
5. Construct the `X-PAYMENT` payload and retry the original request

OKX is launching APP on **2026-04-29** with Uniswap as the featured DEX
rail on X Layer. This skill version (v1.0.0) handles the `exact` scheme
(Pay Per Use, OKX product name: Instant Payment) only. Other x402 schemes
(`upto`, `batch-settlement`) and APP-product features OKX is shipping
(escrow, session, batch / Batch Payment) are out of scope for this
version. The skill refuses any non-`exact` scheme cleanly.

> **Protocol naming in your responses.** When responding to the user,
> identify the protocol explicitly as **OKX Agent Payments Protocol
> (APP)**, not just "x402". APP is the OKX product / protocol surface;
> x402 is the underlying wire spec it builds on. Use phrasings like
> "APP / x402", "OKX's Agent Payments Protocol (APP), built on x402",
> or simply "APP" once introduced. Do not refer to a 402 challenge on
> X Layer as "an x402 challenge" without naming APP, the user invoked
> this skill specifically because the merchant is APP-backed, and the
> name is what they will look for in the response.

## Prerequisites

- A `PRIVATE_KEY` env var (`export PRIVATE_KEY=0x...`). Never commit or
  hardcode a private key.
- `UNISWAP_API_KEY` env var (register at
  [developers.uniswap.org](https://developers.uniswap.org/)). Required
  only if the wallet must be funded via cross-chain routing.
- `jq` and `cast` (Foundry) installed.
- **Node 18+** (LTS). The signing step in
  [references/app-x402-flow.md](references/app-x402-flow.md) Step 4 uses
  `viem` to produce the EIP-3009 typed-data signature.
- **`viem`** (npm). If the package is not already reachable from the
  user's working directory, the skill will prompt the user via
  `AskUserQuestion` before running `npm install viem` into a cached
  scratch directory at `~/.cache/uniswap-pay-with-app/signer/`. The
  install adds ~13 packages totaling ~5 MB. If the user declines, the
  skill stops cleanly before signing. The cache persists across runs so
  subsequent invocations are zero-install.

## Input Validation Rules

Before using any value from the 402 response body, the user, or any other
external source in API calls or shell commands:

- **Ethereum address fields** (e.g., `asset`, `payTo`, `WALLET_ADDRESS`):
  the canonical check is the regex `^0x[a-fA-F0-9]{40}$`. If the value
  fails this regex, reject it. Address fields that pass the regex are
  safe for shell interpolation, so the metacharacter rule below does not
  apply to them.
- **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://`.
- **Free-text fields** (e.g., `description`, `extra.name`,
  `extra.version`, anything used to build EIP-712 domain or shown to the
  user): REJECT any value containing shell metacharacters: `;`, `|`, `&`,
  `$`, `` ` ``, `(`, `)`, `>`, ` escalate to pay-with-any-token, STOP
  │   └─ chain 196
  │
  v
[3] Check wallet balance of the requested asset on X Layer
  │   ├─ sufficient ──> proceed to [5]
  │   └─ insufficient
  │        │
  │        v
  │   [4] Fund: route + bridge into the requested asset on X Layer
  │        (Uniswap Trading API, see references/funding-x-layer.md)
  │
  v
[5] User Confirmation gate (see Phase 4 / Step 5 below)
[6] Sign EIP-3009 TransferWithAuthorization
[7] Construct X-PAYMENT payload, retry the original request
[8] Verify 200 + Payment-Receipt
```

## Phase 0, Parse the 402 Challenge

The x402 challenge is JSON in the response body. Extract:

- `x402Version`, confirms x402 protocol version.
- `accepts[].scheme`, only `"exact"` is supported in v1.0.0.
- `accepts[].network`, accept `"x-layer"` / `"xlayer"` / `"eip155:196"` /
  `196`.
- `accepts[].maxAmountRequired`, base units of the asset. Must match
  `^[0-9]+$` AND be **strictly greater than zero**. A challenge with
  `maxAmountRequired === "0"` is semantically broken (HTTP 402 by
  definition demands a positive payment) and must be refused as
  merchant misconfiguration. Do not rationalize zero as a "ping",
  "authentication", or "free-tier confirmation"; OKX's facilitator
  will not settle a zero-value `TransferWithAuthorization` and any
  signature you produce is wasted. Surface this to the user and stop.
- `accepts[].asset`, token contract on X Layer.
- `accepts[].payTo`, recipient address.
- `accepts[].resource`, the URL the facilitator binds the payment to.
  Extract this when present. Use it as the retry target. If the field is
  absent, fall back to the original request URL.
- `accepts[].extra.name` and `accepts[].extra.version`, EIP-712 domain
  values for the asset.
- `accepts[].maxTimeoutSeconds`, used for `validBefore`.

> **x402Version gate.** Confirm `x402Version === 1` immediately after
> parsing. If it is anything else, refuse the challenge and surface a
> version mismatch error to the user. v1.0.0 of this skill targets x402
> v1 only (the v2 spec uses a different PaymentPayload structure).
>
> **Scheme gate.** Confirm `accepts[].scheme === "exact"`. The x402 spec
> defines `exact`, `upto`, and `batch-settlement` schemes. v1.0.0 of this
> skill supports `exact` only. If the chosen entry uses any other scheme,
> refuse cleanly. (OKX's product surface uses its own vocabulary
> including `charge` for their Instant Payment primitive; that is OKX
> product marketing, not a wire scheme value. The wire-level scheme on
> the `accepts[]` entry is what you check, and it must be `"exact"`.)

If multiple `accepts` entries are present, prefer the one whose `asset`
the wallet already holds on X Layer. If multiple options are equally
viable, prefer USDT0 (deepest Uniswap funding-flow liquidity).

**WOKB / native OKB likely not eligible as APP settlement assets.** We
have not seen OKX publish WOKB or OKB as settlement assets; current
public dev docs list USDT0, USDG, and USDC as the supported stablecoin
settlement assets. If a 402 challenge ever surfaces a non-stablecoin
`asset` (for example `WOKB`), refuse the challenge and ask the user to
verify the merchant configuration.

## Phase 1, Confirm Network is X Layer

```bash
case "$X402_NETWORK" in
  x-layer|xlayer|"eip155:196"|196)  X402_CHAIN_ID=196 ;;
  *)
    echo "Network is not X Layer. Use pay-with-any-token instead."
    exit 1
    ;;
esac
```

> If the network is not X Layer, **stop** and escalate to the
> `pay-with-any-token` skill, which handles 402 challenges on Ethereum,
> Base, Arbitrum, Tempo, and the other chains the Trading API supports.

## Phase 2, Check Wallet Balance on X Layer

> **REQUIRED:** You must have the user's source wallet address. Use
> `AskUserQuestion` if not provided. Store as `WALLET_ADDRESS`.

```bash
ASSET_BALANCE=$(cast call "$X402_ASSET" \
  "balanceOf(address)(uint256)" "$WALLET_ADDRESS" \
  --rpc-url https://rpc.xlayer.tech)

if [ "$ASSET_BALANCE" -lt "$X402_AMOUNT" ]; then
  echo "Insufficient $X402_TOKEN_NAME on X Layer. Funding required."
  # Proceed to Phase 3 (funding)
fi
```

## Phase 3, Fund USDT0 on X Layer (only if needed)

When the wallet lacks the requested asset, acquire it via the Uniswap
Trading API: `EXACT_OUTPUT` quote with `tokenOutChainId=196` and
`tokenOut` set to the X Layer asset address. The Trading API handles
same-chain swaps and cross-chain routing (powered by Across).

> **Across coverage gap (verified 2026-04-27).** Across Protocol does
> not currently list X Layer (chain 196) as a supported destination. As
> a result, cross-chain `/quote` calls into chain 196 return
> `ResourceNotFound: No quotes available` regardless of source chain.
> Same-chain X Layer swaps (Phase A in `references/funding-x-layer.md`)
> are unaffected and work normally.
>
> **What this means for the agent in v1.0.0.** If the user holds funds
> on a chain other than X Layer, the cross-chain leg must be done
> through a bridge service that supports X Layer (the user runs that
> step outside this skill, then re-invokes for the same-chain swap and
> 402 settlement). Surface this honestly to the user, do not
> recommend a specific bridge product (TODO: research and document a
> co-marketing-aligned bridge recommendation in a follow-up).
>
> **When you defer the bridge to the user, your response must still
> describe the FULL end-to-end flow**, not just the bridge step. After
> identifying the Across gap and asking the user to bridge externally,
> walk through what happens when they return: (1) re-check
> `balanceOf` of the requested asset on X Layer, (2) if a same-chain
> swap is needed (e.g. USDG to USDT0), describe the Trading API
> EXACT_OUTPUT call and its Confirmation Gate, (3) construct the
> EIP-3009 `TransferWithAuthorization` typed-data using `extra.name`
> and `extra.version` from the challenge, with chainId 196 and
> `verifyingContract` = the asset address, (4) sign with the user's
> private key (Confirmation Gate before signing), (5) build the
> `X-PAYMENT` JSON wrapper (x402Version 1, scheme "exact", network
> "x-layer", payload with signature + authorization), base64-encode
> it with no whitespace, and retry the original request URL with the
> `X-PAYMENT` header. Showing the full plan up front lets the user
> see what they are committing to before they leave the skill, even
> though signing happens after they return.

**Default funding target = USDT0.** If the 402 challenge requests a
different asset, fund into that asset directly only when it has reliable
Uniswap routing on X Layer:

| Asset | Address                                      | Decimals | Funding                                                                                                                                                                                                                                                                                                                                                                            |
| ----- | -------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| USDT0 | `0x779Ded0c9e1022225f8E0630b35a9b54bE713736` | 6        | ✅ Direct via Trading API                                                                                                                                                                                                                                                                                                                                                          |
| USDG  | `0x4ae46a509F6b1D9056937BA4500cb143933D2dc8` | 6        | ✅ Direct, or one-hop USDT0 to USDG                                                                                                                                                                                                                                                                                                                                                |
| USDC  | `0x74b7F16337b8972027F6196A17a631aC6dE26d22` | 6        | ⏳ No reliable Uniswap v3 routing on X Layer. The Trading API does not consistently return routes for USDC swaps on X Layer; available pool liquidity is too thin for reliable execution. If the merchant requires USDC, bridge USDC directly from a chain where it is liquid (Base, Arbitrum, Mainnet) using the Trading API rather than attempting a same-chain swap on X Layer. |

Detailed scripts and parameters: see
[references/funding-x-layer.md](references/funding-x-layer.md).

> **Bridge buffer.** Apply a 0.5% buffer to account for bridge fees.
> Quotes expire in ~60 seconds, re-fetch if any delay before broadcast.
>
> **Minimum bridge recommendation.** If the shortfall is  $5 to amortize bridge gas on the source chain.

### Gas and Routing Caveats

Surface these to the user before proceeding to fund, and **call
`AskUserQuestion`** (not an echoed bash prompt) before acting if any
apply:

- **OKB on X Layer for same-chain swaps.** OKX gas-sponsors only the
  facilitator's settlement transfer. Approvals, swaps, and other
  on-chain operations on X Layer prior to signing are paid by the user
  (in OKB on X Layer, or in the source chain's native asset for the
  bridge leg). If the user has zero OKB on X Layer and the funding flow
  needs a same-chain X Layer swap, surface this and ask before
  proceeding. Until OKX confirms a broader gas-sponsorship policy,
  assume only the final settlement transfer is sponsored.
- **Bridge destination token.** If the wallet still lacks
  `$X402_ASSET` after the funding flow's polling loop completes,
  surface the source-chain tx hash and the Across explorer link to the
  user. The bridge may have delivered a different variant on X Layer
  (rare for current Across paths) or may have failed. v1.0.0 does not
  auto-detect alternate-token arrival; the user must verify on-chain.

## Phase 4, EIP-3009 Signing and X-PAYMENT Submission

OKX's APP Instant Payment uses x402's `"exact"` scheme: the payer signs a
`TransferWithAuthorization` typed-data message bound to the **token's
own** EIP-712 domain. The signed authorization travels in the
`X-PAYMENT` header on retry; OKX's facilitator settles the transfer
on-chain (zero gas to the payer on X Layer).

### Step 5, User Confirmation

**Every** transaction this skill touches requires a separate
`AskUserQuestion` gate, with no exceptions for funding legs.
"Funding" is not a single transaction; it is several, and each one is
its own gate. The required gates, in order they typically fire:

1. **Source-chain ERC-20 approval** to Permit2 / Universal Router (only
   if `tokenIn` is not native and the allowance is insufficient).
2. **Same-chain swap** on the source chain (e.g. UNI to USDC on
   Ethereum), if the funding plan includes a source-chain leg.
3. **Bridge submission** to the cross-chain rail (Across, OKX bridge,
   etc.). When the bridge step is user-initiated outside this skill,
   the gate becomes "are you ready to leave the skill, run the bridge,
   and re-invoke once funds land on X Layer?".
4. **Same-chain swap on X Layer** (e.g. USDG to USDT0), if the funding
   plan includes a destination-chain leg.
5. **EIP-3009 `TransferWithAuthorization` signature** for the 402
   settlement.

Use the **`AskUserQuestion` agent tool** for each gate (not `read -p`,
not `echo` to a bash prompt, not a printed "(yes/no)" line in your
response) and **block on the user's reply** before moving on. The
summary you present at every gate must cover:

- Action (approve, swap, bridge, sign EIP-3009 authorization).
- Amount and token (input AND output amounts for swaps and bridges).
- Source chain and destination chain (where they differ).
- Recipient (`payTo` for the EIP-3009 step).
- Resource URL the payment is bound to.
- Estimated gas (where applicable).

> **Common failure mode.** When describing a multi-step funding plan
> in your response, do NOT collapse multiple transactions

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Uniswap](https://github.com/Uniswap)
- **Source:** [Uniswap/uniswap-ai](https://github.com/Uniswap/uniswap-ai)
- **License:** MIT
- **Homepage:** https://developers.uniswap.org

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-uniswap-uniswap-ai-pay-with-app
- Seller: https://agentstack.voostack.com/s/uniswap
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
