x402 on Gonka
checking…

Git: gonkalabs Git is temporarily unavailable. Download the source from this website — Source.

Agents & buyers

Treat a paid Gonka URL like any other HTTP resource. On 402, sign a transfer locally and retry. Never send the private key to the facilitator or the seller.

Request cycle

  1. Call the paid URL with whatever method the seller documents (GET /demo is the example).
  2. If the status is not 402, you are done — the resource was free or already paid.
  3. Read PAYMENT-REQUIRED. It is standard base64 JSON. The body is the same object, useful for curl.
  4. Pick one entry from accepts (GNK or USDC unless the seller only lists one).
  5. Build and sign a Gonka TxRaw that pays payTo at least amount of asset.
  6. Repeat the original request with PAYMENT-SIGNATURE set to the base64 payment payload.
  7. On 200, read PAYMENT-RESPONSE for the tx hash. Look it up on gonka.gg.

A live cycle against /demo produced 23B76D1281F9EFCC7AFC90659480CF3219A7099959C0513720769F700E9B73B2. Command, RPC checks, and the explorer link are on Get started.

Choose an accept

Each accepts[] item is a price quote. You must satisfy one of them exactly as advertised:

schemeMust be exact.
networkMust be cosmos:gonka-mainnet.
amountAtomic units. Paying more is allowed; paying less is rejected.
assetngonka or the USDC CW-20 address.
payToMerchant gonka1…. The tx recipient must match.
maxTimeoutSecondsSet authorization.timeoutAt to now plus a value below this (the CLI uses 55s).
extra.paymentFlowupfront — expect the seller to settle before serving you.

Sign the payment

GNK

One /cosmos.bank.v1beta1.MsgSend: from your address, to payTo, amount amount, denom ngonka. Fee is 0ngonka. Gas limit 120000 is what the facilitator expects.

USDC

One /cosmwasm.wasm.v1.MsgExecuteContract against the USDC contract, message:

{
  "transfer": {
    "recipient": "<payTo>",
    "amount": "<atomic amount>"
  }
}

Signing rules

The CLI in this repo already builds that tx. Roll your own signer if you already have CosmJS or inferenced.

Retry with the header

PAYMENT-SIGNATURE is base64 of:

{
  "x402Version": 2,
  "accepted": { "...the PaymentRequirements you chose" },
  "payload": {
    "signature": "<base64 64-byte secp256k1 signature>",
    "authorization": {
      "from": "gonka1…",
      "to": "gonka1…",
      "amount": "1000",
      "denom": "ngonka",
      "timeoutAt": 1710000000
    },
    "signedTx": "<base64 protobuf TxRaw>"
  }
}

For USDC, accepted.asset and authorization.denom are the CW-20 contract address. Field-level meaning is on Protocol.

Fetch wrapper

Sketch for an agent runtime. Sign buildAndSign(accepted) with your existing Gonka wallet.

async function paidFetch(url, key, opts = {}) {
  const first = await fetch(url, opts);
  if (first.status !== 402) return first;
  const required = JSON.parse(atob(first.headers.get("PAYMENT-REQUIRED")));
  const accepted = required.accepts[0];
  const payload = await buildAndSign(accepted, key);
  return fetch(url, {
    ...opts,
    headers: {
      ...(opts.headers || {}),
      "PAYMENT-SIGNATURE": btoa(JSON.stringify(payload)),
    },
  });
}

Retries and failures

Every code is listed on Errors.