Loading...
Loading...
Pay HTTP 402 payment challenges issued by OKX's Agent Payments Protocol (APP) on X Layer using tokens from any chain via the Uniswap Trading API. Use this skill whenever the user encounters a 402 challenge whose network resolves to X Layer (chain 196), mentions "APP", "Agent Payments Protocol", "OKX agent payment", "OKX Onchain OS", "OKX agentic wallet", "x402 on X Layer", "USDT0", "x42", "Instant Payment", "Batch Payment", "pay for X Layer API", or wants to pay an OKX-backed merchant. Even when the user does not explicitly say APP, prefer this skill for any 402 challenge whose network resolves to X Layer (chain 196). For 402 challenges on other chains (Ethereum, Base, Arbitrum, Tempo) use pay-with-any-token instead.
npx skill4agent add uniswap/uniswap-ai pay-with-appTransferWithAuthorizationX-PAYMENTexactuptobatch-settlementexactProtocol 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.
PRIVATE_KEYexport PRIVATE_KEY=0x...UNISWAP_API_KEYjqcastviemviemAskUserQuestionnpm install viem~/.cache/uniswap-pay-with-app/signer/assetpayToWALLET_ADDRESS^0x[a-fA-F0-9]{40}$^[0-9]+$https://descriptionextra.nameextra.version;|&$`()><\'"extra.name402 from X Layer-backed resource
│
v
[1] Parse the x402 challenge (Phase 0 below)
│
v
[2] Confirm network resolves to X Layer (chain 196)
│ ├─ not chain 196 ──> 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-Receiptx402Versionaccepts[].scheme"exact"accepts[].network"x-layer""xlayer""eip155:196"196accepts[].maxAmountRequired^[0-9]+$maxAmountRequired === "0"TransferWithAuthorizationaccepts[].assetaccepts[].payToaccepts[].resourceaccepts[].extra.nameaccepts[].extra.versionaccepts[].maxTimeoutSecondsvalidBeforex402Version gate. Confirmimmediately 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).x402Version === 1Scheme gate. Confirm. The x402 spec definesaccepts[].scheme === "exact",exact, anduptoschemes. v1.0.0 of this skill supportsbatch-settlementonly. If the chosen entry uses any other scheme, refuse cleanly. (OKX's product surface uses its own vocabulary includingexactfor their Instant Payment primitive; that is OKX product marketing, not a wire scheme value. The wire-level scheme on thechargeentry is what you check, and it must beaccepts[].)"exact"
acceptsassetassetWOKBcase "$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
;;
esacIf the network is not X Layer, stop and escalate to theskill, which handles 402 challenges on Ethereum, Base, Arbitrum, Tempo, and the other chains the Trading API supports.pay-with-any-token
REQUIRED: You must have the user's source wallet address. Useif not provided. Store asAskUserQuestion.WALLET_ADDRESS
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)
fiEXACT_OUTPUTtokenOutChainId=196tokenOutAcross coverage gap (verified 2026-04-27). Across Protocol does not currently list X Layer (chain 196) as a supported destination. As a result, cross-chaincalls into chain 196 return/quoteregardless of source chain. Same-chain X Layer swaps (Phase A inResourceNotFound: No quotes available) are unaffected and work normally.references/funding-x-layer.mdWhat 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-checkof 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-3009balanceOftyped-data usingTransferWithAuthorizationandextra.namefrom the challenge, with chainId 196 andextra.version= the asset address, (4) sign with the user's private key (Confirmation Gate before signing), (5) build theverifyingContractJSON 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 theX-PAYMENTheader. 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.X-PAYMENT
| Asset | Address | Decimals | Funding |
|---|---|---|---|
| USDT0 | | 6 | ✅ Direct via Trading API |
| USDG | | 6 | ✅ Direct, or one-hop USDT0 to USDG |
| USDC | | 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. |
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, top up to $5 to amortize bridge gas on the source chain.
AskUserQuestion$X402_ASSET"exact"TransferWithAuthorizationX-PAYMENTAskUserQuestiontokenInTransferWithAuthorizationAskUserQuestionread -pechopayToCommon failure mode. When describing a multi-step funding plan in your response, do NOT collapse multiple transactions into a single confirmation question like "Proceed with funding and payment?". Each transaction needs its own gate at the moment it is about to fire. A consolidated upfront "yes" is not consent for later transactions; the user has not seen the live amounts, gas, and recipient at the time those transactions execute.
<!-- markdownlint-disable-next-line -->What a correct gate looks like in your response. Whether you are executing the skill in real time or describing a plan in text, every transaction step MUST appear as its own labelled "Confirmation Gate" block, with both the structured summary and an explicitinvocation. Reproduce this template literally for each gate. Do not collapse the gate into a single line. Do not describe the gate in passive voice ("we will confirm before signing"). Show the gate as a discrete action.AskUserQuestionTemplate (use for every gate, even when there is only one):text### Confirmation Gate N: <Action name> | Field | Value | | ------------ | ---------------------------------------- | | Action | <approve / swap / bridge / sign EIP-3009>| | Amount in | <amount + symbol on source chain> | | Amount out | <amount + symbol on destination chain> | | Source chain | <chain name + id> | | Dest chain | <chain name + id> | | Recipient | <address> | | Resource URL | <url the payment is bound to> | | Est. gas | <amount + token> | Then call AskUserQuestion("Proceed with <action>?") and BLOCK on the user's reply. If anything other than an explicit "yes", stop and report.A response that only lists fields without thestep is not a gate, even if it looks comprehensive. The model's natural inclination is to summarize and continue; resist that inclination, name the gate, and stop.AskUserQuestion("Proceed?") + block
<!-- markdownlint-disable-next-line -->What does NOT count as a confirmation gate. Emitting a bash script that printsand"⚠️ CONFIRMATION REQUIRED"to stdout and then continues with"(yes/no)"is not a gate, because the script proceeds regardless of user input. A correct gate uses theecho "Signing..."tool (or, if the user explicitly opts into shell-only mode, an actual blockingAskUserQuestionfollowed by an explicitread -p/yesbranch in the script). When in doubt, preferno.AskUserQuestion
Shared-wallet race. If the wallet is shared (for example, multiple agents running concurrently against the same key), the balance can be drained between balance check and submit. Re-checkat the moment of confirmation as well.balanceOf
accepts[].resourceDomain warning.is the token contract, not a separate verifier. UseverifyingContractandnamefrom the challenge'sversionfield, do not assume defaults. Different tokens have different domain values. An incorrect domain produces a signature the facilitator will reject with another 402.extraBit-exact UTF-8 for. The EIP-712 domain hash is byte-exact. Theextra.namefield innamemust be passed through unchanged from the challenge bytes. Do not normalize it, do not lowercase it, do not substitute ASCIIextra(U+0054) for UnicodeT(U+20AE), do not collapse Unicode forms (NFC vs NFD). For example, a challenge that returns₮must be signed as"USD₮0"; reading it as"USD₮0"will produce a signature the facilitator rejects with another 402. Pass the raw bytes of"USDT0"straight into the EIP-712 domain.extra.name
| Situation | Action |
|---|---|
402 challenge has no | Inspect challenge body; if |
| Network is not chain 196 | Escalate to |
| Refuse cleanly; surface a version mismatch error. v1.0.0 of this skill targets x402 v1 only. |
| Refuse cleanly; v1.0.0 supports the |
| Refuse cleanly as merchant misconfiguration. HTTP 402 demands a positive payment; OKX's facilitator will not settle a zero-value transfer. Do not sign and do not rationalize zero as a ping, auth check, or free tier. |
| APP requests USDC on X Layer | Surface a clear caveat: USDC has no reliable Uniswap v3 routing on X Layer. Suggest bridging USDC directly from a chain where it is liquid (Base, Arbitrum, Mainnet), or asking about USDT0. |
| Insufficient asset on X Layer | Trigger funding flow (Phase 3) |
| Trading API returns 400 | Log request/response; check amount formatting and address checksums |
| Trading API returns 429 | Back off and retry with exponential delay |
| Quote expired | Re-fetch quote; do not reuse old |
| Bridge times out | Check Across bridge explorer; do not re-submit |
| EIP-3009 signature rejected (402 on retry) | Verify domain |
| Amount mismatch on retry | Recompute base units using on-chain |
On-chain settlement reverts ( | Re-check |
User asks about escrow / session / batch / | Inform that this skill version covers Instant Payment ( |
196https://rpc.xlayer.tech0x779Ded0c9e1022225f8E0630b35a9b54bE7137360x4ae46a509F6b1D9056937BA4500cb143933D2dc80x74b7F16337b8972027F6196A17a631aC6dE26d220xe538905cf8410324e03A5A23C1c177a474D59b2b0x4B2ab38DBF28D31D467aA8993f6c2585981D68040x4f0C28f5926AFDA16bf2506D5D9e57Ea190f9bcA0xDa00aE15d3A71466517129255255db7c0c0956d30xD1b797D92d87B688193A2B976eFc8D577D2043430x000000000022D473030F116dDEE9F6B43aC78BA30x0cBe0dBE1400e57f371a38BD3b9bC80F7C3676dA0x63d62734847E55A266FCa4219A9aD0a02D5F6e02https://trade-api.gateway.uniswap.org/v1x-api-key: $UNISWAP_API_KEYx-universal-router-version: 2.1.1The on-chain Universal Router contract on X Layer is labeled 2.1 (deployed atabove). The Trading API expects the header value0xDa00aE15d3A71466517129255255db7c0c0956d3, which is the API's internal version-string for the routing path that targets the same Universal Router 2.1 contract. The two version strings refer to related but distinct things; do not substitute one for the other.2.1.1
https://web3.okx.com/onchainos/dev-docs/payments/x402-introductionhttps://github.com/okx/onchainos-skillshttps://github.com/coinbase/x402