okx-agent-payments-protocol

$npx mdskill add okx/onchainos-skills/okx-agent-payments-protocol

> **⚠️ READ FIRST — ZERO-TEXT-ON-TRIGGER + NEVER-SKIP-USER-GATES.** > > Between detecting a 402 (or any trigger word) and emitting the first user-facing card — the Step A3.5 recommendation card, or the Step A4 confirmation card — output **ZERO** user-visible text. No "received 402", no "triggered OKX Agent Payments Protocol", no "detected N schemes", no enumeration of schemes / networks / tokens / amounts, no "loading skill", no "正在处理 / 触发 / 检测到 / 收到". The skill-load tool call may run but emits no surrounding prose. > > Exactly **one** confirmation card runs per payment: A3.5's recommendation card (2+ candidates and user picks `yes`) OR A4's confirmation card (single candidate, OR user picked an alternative from A3.5's expanded list). Do NOT skip the applicable card under the pretext of "past user preference" / "streamlining" / "already confirmed once" — those preferences do not exist. Do NOT render both cards back-to-back with the same info — after `yes` on A3.5.5, go straight to Step A5. The next user-visible text after detection MUST be one of the two cards.

SKILL.md

.github/skills/okx-agent-payments-protocolView on GitHub ↗
---
name: okx-agent-payments-protocol
description: "Unified payment dispatcher for agent-to-service payments. Covers x402 (`exact`, `exact+Permit2`, `upto`, `aggr_deferred` schemes), MPP (`charge` / `session` intents), and a2a-pay (`a2a_charge` paymentId flow). Detects HTTP 402 from response headers and routes to the matching scheme reference; also handles a2a paymentId mentions without a 402. Loads references/{exact,aggr_deferred,upto,charge,session,a2a_charge}.md. Returns a ready-to-paste authorization header (x402/MPP) or a tx-hash + status (a2a). Triggers (EN): 402, payment required, x402, x402Version, X-PAYMENT, PAYMENT-REQUIRED, PAYMENT-SIGNATURE, permit2, upto, metered billing, open/close/topup/settle channel, voucher, session payment, channelId, channel_id, paymentId, a2a_, create payment link, payment link, payment status. Triggers (中文): 按量计费、支付上限、支付通道、关闭/充值/续费/结算通道、关闭会话、结算会话、凭证、会话支付、付款链接、创建支付、支付状态. Any close/topup/settle/voucher/refund near a channel_id or session context = MPP mid-session op → load references/session.md."
license: MIT
metadata:
  author: okx
  version: "3.3.9"
  homepage: "https://web3.okx.com"
---

# OKX Agent Payments Protocol (Dispatcher)

> **⚠️ READ FIRST — ZERO-TEXT-ON-TRIGGER + NEVER-SKIP-USER-GATES.**
>
> Between detecting a 402 (or any trigger word) and emitting the first user-facing card — the Step A3.5 recommendation card, or the Step A4 confirmation card — output **ZERO** user-visible text. No "received 402", no "triggered OKX Agent Payments Protocol", no "detected N schemes", no enumeration of schemes / networks / tokens / amounts, no "loading skill", no "正在处理 / 触发 / 检测到 / 收到". The skill-load tool call may run but emits no surrounding prose.
>
> Exactly **one** confirmation card runs per payment: A3.5's recommendation card (2+ candidates and user picks `yes`) OR A4's confirmation card (single candidate, OR user picked an alternative from A3.5's expanded list). Do NOT skip the applicable card under the pretext of "past user preference" / "streamlining" / "already confirmed once" — those preferences do not exist. Do NOT render both cards back-to-back with the same info — after `yes` on A3.5.5, go straight to Step A5. The next user-visible text after detection MUST be one of the two cards.

Unified entry point for three payment paths, distinguished by HTTP signature: **`accepts`-based 402** (challenge in body for v1 or `PAYMENT-REQUIRED` header for v2), **`WWW-Authenticate: Payment` 402** (channel-capable, with `intent="charge"` or `"session"`), and **a2a-pay** (paymentId-based agent-to-agent links, no 402 required). This file owns the shared steps — protocol detection, payload decode, user confirmation gate, wallet status check — then dispatches into the right scheme/intent reference.

> **User-facing terminology — IMPORTANT**
>
> **Rule 1 — Always call it "OKX Agent Payments Protocol", and always render it bolded.** Use the exact English term **OKX Agent Payments Protocol** in user-visible messages regardless of the user's language, and always wrap it in markdown bold (`**OKX Agent Payments Protocol**`) so the user sees it emphasized. Keep it as a fixed English noun phrase even inside otherwise-Chinese sentences. Reserve protocol literals and internal identifiers for CLI invocations, HTTP headers, JSON payloads, and code — never speak them to the user.
>
> **Rule 2 — Do not narrate internal protocol detection.** The dispatch logic (which header was detected, which reference is being loaded, which scheme/intent was selected, TEE vs local-key path) is internal — keep it internal. The user only needs to see: (a) what is being paid, (b) what they need to confirm, (c) the result.
>
> **Rule 2 carve-out — narrow, alternatives list only.** Inside Step A3.5, the literals `exact` / `aggr_deferred` / `charge` may be exposed to the user **only** in the expanded **alternatives list** (the list rendered after the user picks "show others"), because at that point the user is explicitly choosing between schemes. They MUST NOT appear in: the default recommendation card, the "N other methods" summary line, status narration, error displays, post-payment summaries, or anywhere else. The recommendation card shows network / token / amount / recipient only — never the scheme name.
>
> **Rule 3 — Externally-defined protocol literals stay byte-for-byte exact.** The JSON field `x402Version`, the HTTP headers `X-PAYMENT` / `PAYMENT-SIGNATURE` / `PAYMENT-REQUIRED` / `WWW-Authenticate: Payment`, and the reference URL `https://x402.org` MUST appear verbatim wherever the protocol/server requires them — these are externally defined and changing them breaks interop. CLI subcommand names (`onchainos payment pay` / `pay-local` / `charge` / `session ...` / `a2a-pay ...`) are this CLI's own surface and may evolve; refer to them by their current name in CLI invocations and code, but never speak them to the user (Rule 2).
>
> **Example**
>
> (中) `准备通过 **OKX Agent Payments Protocol** 完成本次支付,下面是扣款明细,请确认……`
> (EN) `Preparing a payment via the **OKX Agent Payments Protocol**. Here are the charge details — please confirm before I proceed…`

> **Progress narration counts as user-visible — Rules 1-3 still apply.**
>
> Long-running flows (decode → confirm → wallet check → sign → header assembly → replay) tempt status updates. Every `"正在…"` / `"I'm now…"` line is user-facing. Step labels in this SKILL.md (`Step A3-Accepts`, `Step A3-WWW-Authenticate`) and reference files (`exact` / `aggr_deferred` schemes, `charge` / `session` intents) are internal — do NOT echo them in narration.
>
> | ❌ Don't say | ✅ Say |
> |---|---|
> | "正在处理 `accepts`-based 流程" / "Processing the `accepts`-based path" | "正在通过 **OKX Agent Payments Protocol** 处理本次支付" / "Processing the payment via the **OKX Agent Payments Protocol**" |
> | "CLI 自动选择 `exact` 方案" / "CLI selected the `exact` scheme" / "走 `aggr_deferred` 路径" | "签名完成" / "Signing done" |
> | "组装 `PAYMENT-SIGNATURE` / `X-PAYMENT` 头" / "Assembling the `PAYMENT-SIGNATURE` header" | "正在重放请求" / "Replaying the request" |
> | "检测到 `WWW-Authenticate: Payment` / `PAYMENT-REQUIRED` 协议" / "Detected the channel-based protocol" | _(silent — go straight to the confirmation prompt)_ |
> | "加载 `references/exact.md`" / "Loading the `exact` playbook" | _(silent — internal routing)_ |
> | "进入 `session` 模式 / `charge` 模式" / "Entering `session` intent" | "支付通道已开" / "Channel opened" — describe the user-visible effect, not the internal mode |
> | "TEE 路径 / 本地 key 路径" / "Using TEE signing path" | _(silent — signing path is internal)_ |
> | "This is an HTTP 402 with two payment-protocol headers offering multiple schemes" / "Both indicators present, entering Step A3.5" | _(silent — protocol detection is internal)_ |
> | "收到 HTTP 402,触发 OKX Agent Payments Protocol" / "Received 402, triggering OKX Agent Payments Protocol" | _(silent — skill-load announcement is internal)_ |
> | "检测到两个 scheme:exact (USD₮0) 和 aggr_deferred (USDG),网络 eip155:196" / "Detected 2 schemes on chain 196" | _(silent — scheme + network + token enumeration is internal; only the recommendation card may name them, and only per Rule 2's carve-out scope)_ |
> | "按之前的偏好,直接走支付不再确认" / "Per past preference, skipping confirmation" | _(forbidden — there is no such preference; the recommendation + confirmation gates are mandatory every time)_ |
> | "I have three candidates (exact, aggr_deferred, charge). Per Rule 2 carve-out…" / "候选池里有 3 个 scheme" | _(silent — candidate enumeration is internal; only the final recommendation card is user-visible)_ |
> | "Let me check wallet status / balance first" / "正在查询钱包余额以筛选候选" | _(silent — the balance fetch is an internal precondition for the recommendation)_ |
> | "Wallet logged in (Account 1). Visible balances: 10 USD₮0, 10 USDG. Token addresses don't match — let me verify chain mapping" | _(silent — balance readout, address normalization, and chain-mapping checks are internal)_ |
> | "After balance filtering, 2 candidates remain; applying tie-breakers" / "过滤后剩 2 个,跑 tie-breaker" | _(silent — only emit the recommendation card)_ |

> Read `../okx-agentic-wallet/_shared/preflight.md` before any `onchainos` command. EVM only — CAIP-2 `eip155:<chainId>` (run `onchainos wallet chains` for the list).

## Reference map

| Triggered by | Load |
|---|---|
| 402 with `PAYMENT-REQUIRED` header (v2) or `x402Version` body field (v1), CLI output carries `permit2Authorization` field (covers `exact + Permit2` and `upto` schemes) | `references/upto.md` |
| 402 with `PAYMENT-REQUIRED` header (v2) or `x402Version` body field (v1), CLI output carries `sessionCert` field (and no `permit2Authorization`) | `references/aggr_deferred.md` |
| 402 with `PAYMENT-REQUIRED` header (v2) or `x402Version` body field (v1), CLI output carries `authorization` field (no `sessionCert`, no `permit2Authorization`) | `references/exact.md` |
| 402 with `WWW-Authenticate: Payment`, `intent="charge"` | `references/charge.md` |
| 402 with `WWW-Authenticate: Payment`, `intent="session"` (also: any mid-session op on a `channel_id`) | `references/session.md` |
| User mentions a paymentId / `a2a_...` link / "create payment link" | `references/a2a_charge.md` |

## Skill Routing

| Intent | Use skill |
|---|---|
| Token prices / charts / wallet PnL / tracker activities | `okx-dex-market` |
| Token search / metadata / holders / cluster analysis | `okx-dex-token` |
| Smart money / whale / KOL signals | `okx-dex-signal` |
| Meme / pump.fun token scanning | `okx-dex-trenches` |
| Token swaps / trades / buy / sell | `okx-dex-swap` |
| Authenticated wallet (balance / send / tx history) | `okx-agentic-wallet` |
| Public address holdings | `okx-wallet-portfolio` |
| Tx broadcasting (`feePayer=false` hash mode) | `okx-onchain-gateway` |
| Security scanning (token / DApp / tx / signature) | `okx-security` |

**Channel mid-session ops** (close / topup / settle / voucher / refund mentioned with an active `channel_id`, regardless of fresh 402) → stay here, jump straight into `references/session.md` at the matching phase. **Do NOT** search for a separate `close-channel` / `topup-channel` / `settle-channel` tool — they're all `onchainos payment session ...` subcommands.

---

# Path A: HTTP 402

## Step A1: Send the original request

Make the HTTP request the user asked for. If status is **not 402**, return the body directly — no payment, no wallet check, no other tool calls.

## Step A2: Detect the protocol

```
Priority 1: response.headers['WWW-Authenticate']
  starts with "Payment "        → continue at Step A3-WWW-Authenticate
Priority 2: response.headers['PAYMENT-REQUIRED']
  base64-encoded JSON           → continue at Step A3-Accepts (v2)
Priority 3: response body JSON has "x402Version"
                                → continue at Step A3-Accepts (v1)
Otherwise                       → not a supported payment protocol, stop
```

**Both indicators present** — branch on the WWW-Authenticate intent:

- `intent="session"` offered alongside `accepts`-based options → STOP and ask the user:
  > The server offers two payment styles via the **OKX Agent Payments Protocol**:
  > 1. **Session (multi-request)** — open a channel and issue vouchers per request
  > 2. **One-shot purchase**
  >
  > Which would you like to use?

  Option 1 → continue at Step A3-WWW-Authenticate (session path). Option 2 → drop the session intent and continue at Step A3-Accepts with the accepts options.

- `intent="charge"` offered alongside `accepts`-based options → all options are one-shot; **do not** show the session-vs-one-shot prompt. Decode both protocol families (Step A3-Accepts AND Step A3-WWW-Authenticate), merge the candidates, and let Step A3.5 handle the recommendation.

## Step A3-Accepts: Decode

**v2** — payload is in the `PAYMENT-REQUIRED` response **header** (base64-encoded JSON):

```
headerValue = response.headers['PAYMENT-REQUIRED']
decoded     = JSON.parse(atob(headerValue))
```

**v1** — payload is in the response **body** (direct JSON, not base64):

```
decoded = JSON.parse(response.body)
```

Extract:

```
accepts = decoded.accepts          // pass full array to the CLI later
option  = decoded.accepts[0]       // for display only
```

Save `decoded` for header assembly later — you will need `decoded.x402Version` and `decoded.resource` (v2).

## Step A3-WWW-Authenticate: Decode

Parse the WWW-Authenticate header:

```
Payment id="...", realm="...", method="evm", intent="...", request="<base64url>", expires="..."
```

base64url-decode `request` to get the JSON body. Save:

```
intent              charge | session
amount              base units string (e.g. "1000000")
currency            ERC-20 contract address
recipient           merchant payee address
methodDetails:
  chainId           EVM chain ID (e.g. 196 for X Layer)
  escrowContract    REQUIRED for session, ABSENT for charge
  feePayer          true (transaction mode) | false (hash mode)
  splits            optional, charge only, max 10 entries
  minVoucherDelta   optional, session only
  channelId         optional, session topUp/voucher only — pre-existing channel
suggestedDeposit    optional, session only — suggested initial deposit
unitType            optional — "request" | "second" | "byte" etc.
```

**Method check** — only `method="evm"` is supported here. If `method` is `"tempo"`, `"svm"`, `"stripe"`, etc. → stop and tell the user this dispatcher cannot handle it.

**Challenge expiry** — if `expires=...` (ISO-8601) is in the past, the challenge is dead: re-send the original request to get a fresh 402 before signing. Stale challenges fail with `30001 incorrect params`.

Convert `amount` from base units to human-readable using the token's decimals (typically 6 for USDC/USD₮, 18 for native).

## Step A3.5: Multi-scheme recommendation (when applicable)

**Applies only when** the combined candidate pool contains **2 or more** of `{exact, aggr_deferred, charge}`. Otherwise skip straight to Step A4 with the single available candidate.

> **🔇 Silence rule for A3.5 internals.** Substeps A3.5.1–A3.5.4 (candidate enumeration, wallet-status check, balance fetch, address/chain-mapping normalization, balance filtering, tie-breaker application) are **internal** — produce **no user-facing narration** during them. The only A3.5 output the user sees is (a) the login prompt in A3.5.2 *if* the wallet isn't logged in, and (b) the recommendation card / alternatives list in A3.5.5. Do **not** announce "I'm checking your balance", "Let me verify the chain mapping", "After filtering, X candidates remain", "Per Rule 2 carve-out…", or any other progress chatter between Step A3 finishing and the recommendation card appearing. Just go silent and emit the card.
>
> **🚫 Exactly one user gate per payment, mandatory.** Per payment, the user sees exactly one confirmation surface: A3.5's recommendation card (when 2+ candidates and the user accepts with `yes`), OR A4's per-payment confirmation card (when there's only 1 candidate, OR when the user picked an alternative from A3.5's expanded list). Do not skip the applicable gate on your own initiative — no "past preference", "streamlining", or "they confirmed once before" shortcuts; those preferences do not exist. Equally, do not duplicate gates: after a `yes` on A3.5.5, do NOT also render A4 with the same info.

### A3.5.1: Build the candidate pool

- Each entry in `accepts[]` → one candidate. Scheme = `accepts[i].scheme` (`exact` or `aggr_deferred`).
- A `WWW-Authenticate: Payment` 402 with `intent="charge"` → one candidate. Scheme = `charge`.
- `WWW-Authenticate: Payment` with `intent="session"` is **never** part of this pool — it's handled by the session-vs-one-shot branch in Step A2.

Each candidate carries `{scheme, chainId, tokenAddress, tokenSymbol, amount (atomic), amountHuman, isMainnet}`. Determine `isMainnet` from the chain registry (`onchainos wallet chains` lists chain metadata).

### A3.5.2: Get wallet balance

- If a recent wallet-balance snapshot already exists in conversation context (from an earlier `onchainos wallet balance` call this session), **reuse it** — do not re-query.
- Otherwise, check login first via `onchainos wallet status`:
  - **Not logged in** → ask the user to log in (the recommendation depends on knowing their balance). Don't fall back silently.
  - **Logged in** → query balance:

    ```bash
    onchainos wallet balance
    ```

### A3.5.3: Filter by has-balance

Keep only candidates where the wallet has a non-zero balance for the matching `(chainId, tokenAddress)`.

**Edge case — zero candidates pass the filter**: list **all original candidates** to the user (no recommendation badge, no tie-breakers applied). User picks one; carry it to Step A4.

### A3.5.4: Tie-breakers (apply in order; stop when one wins)

If more than one candidate remains after A3.5.3:

1. **Smallest required payment amount — same-symbol only.** Group remaining candidates by `tokenSymbol`. If they all share a single symbol, the one with the smallest `amountHuman` wins. If the remaining set spans multiple symbols, skip this rule.
2. **Mainnet over testnet.** Drop testnet candidates if any mainnet candidate remains. Different mainnets are equal — no preference between e.g. Ethereum, Base, X Layer.
3. **Scheme priority:** `aggr_deferred` > `exact` > `charge`.

The survivor is the **recommended candidate**. The rest are **alternatives**.

### A3.5.5: Display the recommendation

**Carve-out scoping** — the recommendation card itself does **NOT** contain a `Scheme:` line, and the "N other methods" summary line does **NOT** preview their schemes / amounts / tokens. Scheme literals appear **only** inside the expanded alternatives list, and only when the user explicitly asks for it. Render the card with `N = number_of_alternatives`:

> We recommend paying via the **OKX Agent Payments Protocol**:
>
> - **Network**: `<chain name>` (`eip155:<chainId>`)
> - **Token**: `<symbol>` (`<token address>`)
> - **Amount**: `<human> (<atomic>)`
> - **Pay to**: `<recipient>`
>
> `<N == 0 ? "No other methods available." : "There are <N> other supported method(s) you could use instead.">` Use the recommended method? (yes / show others)

**⚠️ Do NOT inline alternatives in the summary line.** Forbidden: ❌ "There are 2 other methods (exact 0.001 USD₮0, charge 0.0005 USD₮0)". Required: ✅ "There are 2 other supported methods you could use instead." Detail only appears after the user picks "show others".

- **yes** (or `N == 0`) → the recommended candidate becomes the **selected candidate**; continue at Step A4.
- **show others** → only now expand the alternatives list, each row as `<index>. scheme=<exact | aggr_deferred | charge>, network=<…>, token=<…>, amount=<…>`. User picks one by index → that becomes the selected candidate; continue at Step A4.

### A3.5.6: Carry the selection forward

- **`accepts`-based selection** (`exact` or `aggr_deferred` from `accepts[]`) → in Step A6, pass a single-entry accepts array (`'[selected_accept]'`) to `onchainos payment pay` so the CLI cannot deviate from the user's choice.
- **`charge` selection** (from WWW-Authenticate) → in Step A6, take the WWW-Authenticate / `references/charge.md` path; ignore the accepts-based candidates entirely.

Step A4 below now describes the **selected candidate**. Step A5's wallet-status check is already satisfied if A3.5.2 ran the login flow — skip the re-check; just continue to A6.

## Step A4: Display payment details and STOP

**🟢 Skip this step entirely if** the user accepted the recommendation in A3.5.5 with `yes`. The recommendation card already showed network / token / amount / recipient at the same fidelity A4 would — re-rendering them is pure redundancy. Go straight to Step A5 (a no-op if A3.5.2 already handled login) → A6.

**🔴 Run this step normally if** either:
- Step A3.5 did not run at all (single-candidate path — server only offered one scheme), OR
- The user picked an alternative from A3.5's expanded list. The alternatives list is one-line-per-row overview, so the picked candidate still needs full-detail confirmation here.

**⚠️ MANDATORY (when run): Display details and STOP to wait for explicit user confirmation. Do NOT call `onchainos wallet status` or any other tool until the user confirms.**

For **`accepts`-based 402** (`PAYMENT-REQUIRED` header v2 / `x402Version` body v1):

> This resource requires payment via the **OKX Agent Payments Protocol**:
> - **Network**: `<chain name>` (`<option.network>`)
> - **Token**: `<token symbol>` (`<option.asset>`)
> - **Amount**: `<human-readable amount>` (from `option.amount` for v2, or `option.maxAmountRequired` for v1; convert from minimal units using token decimals)
> - **Pay to**: `<option.payTo>`
>
> Proceed with payment? (yes / no)

For **`WWW-Authenticate: Payment` 402**:

> This resource requires payment via the **OKX Agent Payments Protocol**:
> - **Payment type**: `<one-shot payment | session (multiple requests)>` (render in Chinese as `单次支付` / `会话支付(多请求)` — NEVER `单次购买`)
> - **Network**: `<chain name>` (`eip155:<chainId>`)
> - **Token**: `<symbol>` (`<currency address>`)
> - **Amount per request**: `<human-readable>` (atomic: `<amount>`)
> - **Pay to**: `<recipient>`
> - **Who pays gas**: `<server (transaction mode) | you broadcast it yourself (hash mode)>`
> - **Split recipients** (one-shot only, if present): `<N other parties also receive a share>`
> - **Suggested prepaid balance** (session only, if present): `<human-readable>`
>
> Proceed with payment? (yes / no)

- **User confirms** → Step A5.
- **User declines** → stop. No payment, no wallet check.

## Step A5: Check wallet status (only after the user explicitly confirms)

```bash
onchainos wallet status
```

- **Logged in** → Step A6.
- **Not logged in (`accepts`-based path)** → ask the user to choose between (1) wallet login (TEE signing) or (2) local private key (`onchainos payment pay-local`, `exact` scheme only). Don't read files or check env vars until the user picks.
- **Not logged in (`WWW-Authenticate: Payment` path)** → ask the user to log in via email OTP or AK. **TEE-only — no local-key fallback for this path** (only the `accepts`-based path has one).

## Step A6: Hand off to the scheme/intent reference

| Path | Action |
|---|---|
| **`accepts`-based** (`PAYMENT-REQUIRED` header v2 / `x402Version` body v1) | Run `onchainos payment pay --accepts '<JSON.stringify(accepts_to_pass)>'`. Build `accepts_to_pass` from Step A3.5's outcome: if A3.5 ran and the user selected an accepts-based candidate, pass a **single-entry array** containing just that accept (`'[selected_accept]'`); otherwise pass the full `decoded.accepts` array. When the response comes back, branch by which field is present in the CLI output (check in this order — `upto` carries both `permit2Authorization` and `sessionCert`):<br>• `permit2Authorization` present → load **`references/upto.md`** for header assembly + replay (covers both `exact + Permit2` and `upto` scheme)<br>• `sessionCert` present (and no `permit2Authorization`) → load **`references/aggr_deferred.md`** for header assembly + replay (Ed25519 session-key path)<br>• otherwise (`authorization` present) → load **`references/exact.md`** for header assembly + replay (EIP-3009 path)<br>If the user picked the local-key fallback, run `onchainos payment pay-local` instead and load **`references/exact.md`** (only scheme this fallback supports). |
| **`WWW-Authenticate: Payment`, `intent="charge"`** | Load **`references/charge.md`** at "Decide mode". |
| **`WWW-Authenticate: Payment`, `intent="session"`** | Load **`references/session.md`** at "Phase S1: Open Channel" (or jump to S2 / S2b / S3 if the user is mid-session with an active `channel_id`). |

After the reference returns the assembled `X-PAYMENT` / `PAYMENT-SIGNATURE` header or `authorization_header`, replay the original request and surface the response to the user. Suggest follow-ups conversationally — never expose internal field names or skill IDs.

---

# Path B: a2a-pay (paymentId-based, no 402)

The user invokes this path explicitly — by mentioning a `paymentId` / `a2a_...` link, asking to "create a payment link", or asking to check a2a payment status.

## Step B1: Identify the role

| User says… | Load | Role |
|---|---|---|
| "create payment link" / "generate payment" / `--amount`/`--recipient` | `references/a2a_charge.md` → "Seller — Create" | Seller |
| Provides a `paymentId` / `a2a_...` to pay | `references/a2a_charge.md` → "Buyer — Pay" | Buyer |
| Provides a `paymentId` and asks for status | `references/a2a_charge.md` → "Status — Query" | Either |

If the user says only "I want to pay" without a paymentId — STOP and ask the user to provide the seller-issued paymentId. Do not attempt anything else.

## Step B2: Wallet status

Both `create` and `pay` require a live wallet session. Run `onchainos wallet status`:

- **Logged in** → proceed (load the reference and follow it).
- **Not logged in** → ask the user to log in via `onchainos wallet login` or `onchainos wallet login <email>`. **Do NOT sign without a live session.**

## Step B3: Hand off to `references/a2a_charge.md`

The reference contains the full create/pay/status flow including the auto-poll-to-terminal logic and trust-delegation note. Buyer-side trust is delegated to the upstream caller — the buyer signs whatever the on-server challenge declares. Cross-checking the paymentId against the agreed terms is the upstream's responsibility, NOT this dispatcher's.

---

# Cross-cutting

## Reading seller errors (`WWW-Authenticate: Payment` / a2a-pay)

When the seller rejects, do NOT show raw JSON or just the numeric code. Extract the human-readable explanation in priority order, use the first non-empty match:

1. `body.reason` (mppx, OKX TS Session)
2. `body.detail` (RFC 9457 ProblemDetails)
3. `body.message`
4. `body.msg` (OKX SA API)
5. `body.error`
6. `body.title` (RFC 9457 short title — fallback only)
7. fallthrough — format the whole body and add the HTTP status

Format:

> ❌ Seller rejected: `<reason text>` (code `<code if present>`, HTTP `<status>`)

## Amount display

All user-facing amounts in BOTH human and atomic form: `<human> (<atomic>)`, e.g. `0.0004 USDC (400)`, `1.5 ETH (1500000000000000000)`. Compute via `amount / 10^decimals` from the challenge `currency` token.

| Token | Decimals | 1 unit in minimal | Example |
|---|---|---|---|
| USDC | 6 | `1000000` | `1000000` → 1.00 USDC |
| USDT | 6 | `1000000` | `2500000` → 2.50 USDT |
| USDG | 6 | `1000000` | `500000`  → 0.50 USDG |
| ETH | 18 | `1000000000000000000` | `10000000000000000` → 0.01 ETH |

For any symbol not in the table: never assume — query `okx-dex-token` for the token's decimals first. If you cannot resolve them, render `<minimal> <symbol>` and append `unknown decimals — please double-check the seller-provided amount`. Do not block the flow.

## Suggest next steps

After a successful payment + response, suggest conversationally:

| Just completed | Suggest |
|---|---|
| Successful HTTP 402 replay | Check balance impact via `okx-agentic-wallet`; or make another request to the same resource |
| Successful a2a payment | Verify post-payment balance via `okx-agentic-wallet` |
| 402 on replay (expired) | Retry with a fresh signature |
| Channel session in progress | Issue another voucher when the next request arrives; close the channel when done |

More from okx/onchainos-skills

SkillDescription
okx-a2a-paymentDEPRECATED legacy alias — a2a-pay support has been merged into `okx-agent-payments-protocol` (see `references/a2a_charge.md`). This stub exists only so that legacy invocations referencing the old name resolve to a meaningful redirect. If you land here, immediately load `okx-agent-payments-protocol` via the Skill tool and follow it instead. Do NOT execute any payment logic from this stub. All paymentId / a2a_... / payment-link / payment-status triggers now route directly to `okx-agent-payments-protocol` (Path B in its SKILL.md).
okx-agentic-walletAUTHORITATIVE source for OKX Agentic Wallet and its Gas Station feature (OKX's stablecoin-gas feature via EIP-7702 + Relayer; always follow references/gas-station.md). Invoke for any wallet action and any Gas Station question. Wallet actions: login, OTP verify, add / switch / status / logout account, balance, assets, holdings, addresses, deposit / receive / top up, send (native + ERC-20 / SPL, transfer ETH / USDC, pay someone), contract call (approve, swap calldata, contract function), history (list + tx detail by orderId / txHash / uopHash), check order status, sign-message (personalSign EVM + Solana, EIP-712 EVM only), TEE signing, export wallet / mnemonic. Gas Station questions: what is / how it works / supported chains + stablecoins / fees / enable or disable / revoke 7702 / change default gas token.
okx-audit-logUse this skill when the user asks to export audit logs, find audit log location, view command history, 导出日志, 查看日志, 日志路径, 操作记录, 调用记录, 命令历史. Do NOT use for wallet balance, token search, swap, or any other on-chain operation — use the corresponding skill instead.
okx-dapp-discovery|
okx-defi-investOKX-aggregated DeFi discovery and execution — for users who want OKX to find and route to the best protocol WITHOUT naming a specific DApp. **If the user names ANY third-party protocol/DApp as destination (Aave, Lido, PancakeSwap, Uniswap, Curve, Compound, Morpho, Pendle, Kamino, Raydium, Hyperliquid, Polymarket, etc.), route to okx-dapp-discovery — NOT here, even if the verb (deposit, stake, add liquidity, borrow, claim) matches.** DApp-agnostic triggers: 'invest in DeFi', 'earn yield on stablecoins', 'find best APY', 'deposit/stake for yield', 'search DeFi products', 'redeem/withdraw position', 'claim DeFi rewards', 'borrow against asset', 'repay loan', 'add/remove CLMM liquidity', 'APY/TVL history', 'CLMM depth chart'. Also covers DeFi investing, yield farming, lending, borrowing, staking, liquidity pools, APY/TVL trends. Do NOT use for: DEX swaps (okx-dex-swap), token prices (okx-dex-market), wallet balances (okx-wallet-portfolio), positions-only views (okx-defi-portfolio).
okx-defi-portfolioUse this skill to 'check my DeFi positions', 'view DeFi holdings', 'show my DeFi portfolio', 'what DeFi am I invested in', 'show my staking positions', 'show my lending positions', 'DeFi balance', 'DeFi 持仓', '查看DeFi持仓', '我的DeFi资产', '持仓详情', '持仓列表', or mentions viewing DeFi holdings, positions, portfolio across protocols — when the user does NOT name a specific DApp. Covers positions overview and per-protocol position detail. Do NOT use for deposit/redeem/claim operations — use okx-defi-invest. Do NOT use for wallet token balances — use okx-wallet-portfolio. Do NOT use for DEX spot swaps — use okx-dex-swap. Do NOT use when the user names a specific third-party DApp by name (e.g. 'show my Aave positions', 'my Hyperliquid balance', 'check my Polymarket holdings') — route to okx-dapp-discovery instead, which loads the DApp's plugin for protocol-native position views.
okx-dex-bridgeUse this skill to bridge tokens, cross-chain swap/transfer, move assets between chains, get cross-chain quotes, compare bridge fees, find the cheapest/fastest route, build bridge calldata, check bridge status, track a cross-chain transaction, list supported chains or bridge protocols, or when the user mentions bridging ETH/USDC/tokens from one chain (Ethereum, BSC, Polygon, Arbitrum, Base, Optimism, etc.) to another. Routes through multiple bridge protocols (Stargate, Across, Relay, Gas.zip) for optimal execution. Supports fee comparison, destination address specification, approval management, and full lifecycle status tracking until fund arrival.
okx-dex-marketHARD BLOCK — NEVER use this skill for prediction-market / Polymarket UpDown queries. Route to okx-dapp-discovery when (a) a named DApp (Polymarket/Aave/Hyperliquid/PancakeSwap/Morpho) appears with any timeframe, OR (b) any 涨跌 / updown / 'up or down' phrase appears for BTC/ETH/SOL/XRP/BNB/DOGE/HYPE (e.g. '<COIN> 涨跌市场', '5 分钟涨跌', 'BTC up or down'). Example: 'BTC 5 分钟涨跌市场' → okx-dapp-discovery (NOT K-line). These are Polymarket prediction markets, not on-chain price queries. Use THIS skill for on-chain market data: token prices/价格, K-line/OHLC/candlestick/K线 charts, index prices, and wallet PnL/盈亏分析 (win rate, my wallet's DEX trade history, realized/unrealized PnL per token). Triggers: 'token price', 'price chart', 'K线', 'OHLC', 'how much is X worth', 'show my PnL', '胜率', '盈亏', 'my wallet DEX history', 'realized/unrealized profit'. NOTE: WebSocket script/脚本/bot → okx-dex-ws. ALSO the OWNER of Market API payment handling — route here (NOT okx-agent-payments-protocol) for: 'onchainos market 报 402', 'market price 402', 'market API pricing/计费/收费', Basic/Premium tier/quota/额度/免费额度, 'ok-web3-openapi-pay' header, 30 天过渡期/grace period, any MARKET_API_* notification code (NEW_USER_INTRO / OLD_USER_GRACE / OLD_USER_POST_GRACE_* / *_OVER_QUOTA), or 'confirming:true' response from onchainos market commands.
okx-dex-signalUse this skill for smart-money/whale/KOL/大户 activity tracking, aggregated buy signal/信号 alerts, and leaderboard/牛人榜 rankings. Covers: (1) address tracker — raw DEX transaction feed for smart money, KOL, or custom wallet addresses; (2) aggregated buy-only signal alerts — tokens bought collectively by smart money/KOL/whales; (3) leaderboard — top traders by PnL, win rate, volume, or ROI. Use when the user asks 'what are smart money buying', '聪明钱最新交易', 'KOL交易动态', '追踪聪明钱', 'track address trades', '大户在买什么', 'whale signals', 'smart money alerts', '信号', '大户信号', 'top traders', '牛人榜', or wants to monitor notable wallet activity. Also handles Market API payment/计费/x402/402, Basic/Premium tier/quota/额度 questions, and MARKET_API_*_OVER_QUOTA / confirming:true responses on signal, leaderboard, or tracker endpoints. NOTE: if the user wants to write a WebSocket script/脚本/bot, use okx-dex-ws instead.
okx-dex-socialSurfaces social-layer signals for crypto markets. Three capability groups: news (latest aggregated crypto news feed, filter articles by coin symbol, run full-text keyword searches, fetch a single article in full, and list available upstream platforms — blockbeats, odaily, theblock and similar — for use as filters); sentiment (rank coins by social mention volume over 1h / 4h / 24h, plus per-coin bullish/bearish/neutral counts with an optional time-bucketed trend); vibe (per-contract hotness score over 24h / 72h / 7d / 30d with timeline and sample KOLs per bucket, plus a TOP50 KOL leaderboard sortable by engagement, mentions, or impressions). Triggers: 'latest crypto news', 'BTC headlines', 'search news for X', 'is BTC bullish', 'hottest coins by chatter', 'who is tweeting about <token>', 'vibe score', 'first-mention KOL', and Chinese variants like '最新加密新闻', '搜索新闻', '市场情绪', '情绪排行', 'KOL榜', '热度走势'. Also handles x402/402 payment, quota, MARKET_API_*_OVER_QUOTA, and confirming:true notifications on social endpoints.