Агенты и покупатели
Относитесь к платному URL Gonka как к любому HTTP-ресурсу. При 402 подпишите перевод локально и повторите запрос. Никогда не отправляйте приватный ключ фасилитатору или продавцу.
Цикл запроса
- Вызовите платный URL методом, который указал продавец (пример —
GET /demo). - Если статус не 402, готово — ресурс бесплатный или уже оплачен.
- Прочитайте
PAYMENT-REQUIRED. Это стандартный base64 JSON. Тело — тот же объект, удобно для curl. - Выберите одну запись из
accepts(GNK или USDC, если продавец не указал только одну). - Соберите и подпишите Gonka
TxRaw, которая платитpayToне меньшеamountактиваasset. - Повторите исходный запрос с
PAYMENT-SIGNATURE, равным base64 payload платежа. - При 200 прочитайте
PAYMENT-RESPONSEради хеша транзакции. Найдите её на gonka.gg.
Выбор accept
Каждый элемент accepts[] — котировка. Нужно выполнить ровно одну из них, как объявлено:
scheme | Должно быть exact. |
|---|---|
network | Должно быть cosmos:gonka-mainnet. |
amount | Атомарные единицы. Платить больше можно; меньше — отказ. |
asset | ngonka или адрес CW-20 USDC. |
payTo | Адрес продавца gonka1…. Получатель в транзакции должен совпасть. |
maxTimeoutSeconds | Поставьте authorization.timeoutAt на сейчас плюс значение меньше этого (CLI использует 55 с). |
extra.paymentFlow | upfront — продавец проводит settle до выдачи ресурса. |
Подпись платежа
GNK
Одно /cosmos.bank.v1beta1.MsgSend: с вашего адреса, на payTo, сумма amount, denom ngonka. Комиссия 0ngonka. Лимит газа 120000 — то, что ожидает фасилитатор.
USDC
Одно /cosmwasm.wasm.v1.MsgExecuteContract к контракту USDC, сообщение:
{
"transfer": {
"recipient": "<payTo>",
"amount": "<atomic amount>"
}
}Правила подписи
- SIGN_MODE_DIRECT над
sha256(SignDoc). - secp256k1, компактная подпись 64 байта (r||s).
- Публичный ключ в AuthInfo должен давать адрес
from. chain_id—gonka-mainnet.account_numberиsequenceдолжны быть живыми значениями с LCD/cosmos/auth/v1beta1/accounts/{from}. Устаревший sequence отклоняется какstale_sequence.
CLI в этом репозитории уже собирает такую транзакцию. Свой подписант можно сделать на CosmJS или inferenced.
Повтор с заголовком
PAYMENT-SIGNATURE — это base64 объекта:
{
"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>"
}
}Для USDC accepted.asset и authorization.denom — адрес контракта CW-20. Смысл полей — в Протоколе.
Обёртка fetch
Набросок для рантайма агента. Подпишите buildAndSign(accepted) своим кошельком Gonka.
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)),
},
});
}Повторы и ошибки
- Не транслируйте транзакцию сами. Фасилитатор транслирует приложенный
signedTx. - Если settle вернул
stale_sequence, заново запросите аккаунт и подпишите снова. Старый payload не переиспользуйте. - Если получили
replayed_payment, этотTxRawуже проведён. Подпишите новую транзакцию (новый sequence). settlement_pendingзначит, что транзакция ушла в сеть, но включение в блок не подтвердилось вовремя. Проверьте хеш в эксплорере, прежде чем платить снова.- На платящем аккаунте должен быть достаточный баланс.
/verifyэто проверяет;/settleупадёт в сети, если баланса нет.
Все коды — на странице Ошибки.