Демо-режим: референсная витрина для eSIM-операторов. Цены живые, оплата отключена. Запустить своего оператора →
Travel eSIM · demo
Русский

Кейсы: ИИ-агент покупает eSIM, а потом получает деньги назад

Содержание

Реальные прогоны кита с транзакциями, чтобы каждый шаг можно было проверить ончейн. Кейс 2 (раздел 10) — тот же агент покупает нашу капабилити через хаб. В кейсе 3 (раздел 11) два покупателя — агент для разработки в терминале и ARGUS, а хаб считает доставки продавца по подписанным квитанциям покупателей. Первый кейс — путь агента целиком и в обе стороны: ИИ-агент находит предложение, платит за него в USDC по x402, передаёт eSIM своему владельцу, а потом просит возврат, и узел продавца возвращает деньги без чьих-либо ручных действий с кошельком.

1. Что произошло

15 октября 2026 года владелец ARGUS — личного ИИ-агента — написал ему в Telegram: купи мне самую дешёвую eSIM в Турцию. ARGUS запросил предложения у узла продавца из кита, выбрал «Турция, 500 МБ на 7 дней» за 0.31 USDC, попросил у владельца подтверждение и заплатил из своего кошелька. Через несколько секунд у владельца в чате были QR-код и код активации. Сам ARGUS их не видел.

Через 34 минуты владелец попросил ARGUS сделать возврат. eSIM не была установлена, поэтому узел продавца отменил её у оптовика и отправил 0.31 USDC обратно на кошелёк агента. Все кошельки и оптовый баланс вернулись к исходным значениям.

Продавцом был закрытый тестовый стенд кита: обычный узел продавца, продающий по себестоимости и доступный только с хоста агента. Ничего в прогоне не имитировалось.

2. Кто участвовал

УчастникКто этоАдрес или место
Владелецчеловек, на которого работает ARGUS; подтверждает каждый платёж в Telegramличный чат в Telegram
ARGUSагент (покупатель); платит из своего кошелька0x428f2Be4327908948e3B1915C55ddF8fA6bf73cc
Узел продавцаузел rails/ из кита (продавец) с включёнными автоматическими возвратамиhttps://esim.modelmarket.dev/stand
Кошелёк продавцапринимает платежи и платит возвраты (PAY_TO и REFUND_KEY_FILE — один кошелёк)0xF47161fBB56D0D910a17e503C8292903F41BbAE2
Фасилитаторфасилитатор x402 от Coinbase: проверяет каждый подписанный перевод и отправляет его в сеть, оплачивая газCDP
ОптовикeSIM Access: выпускает и отменяет профильаккаунт оператора

3. Вся цепочка

sequenceDiagram
    autonumber
    actor O as Владелец (Telegram)
    participant A as ARGUS (агент)
    participant S as Узел продавца
    participant F as Фасилитатор x402
    participant W as eSIM Access
    O->>A: купи мне самую дешёвую eSIM в Турцию
    A->>S: POST /quote {"country":"TR"}
    S-->>A: TR_0.5_7, 500 МБ, 7 дней, 0.31 USDC (с подписью)
    A->>O: подтвердить esim_buy?
    O-->>A: /yes
    A->>S: POST /order {"offer_id":"TR_0.5_7"}
    S-->>A: 402 Payment Required: 0.31 USDC на кошелёк продавца
    A->>S: тот же заказ с PAYMENT-SIGNATURE (EIP-3009, подпись ARGUS)
    S->>F: verify
    S->>W: заказ одного профиля (идемпотентно по платежу)
    W-->>S: профиль 26101505200012
    S->>F: settle
    F-->>S: tx 0x617efd7a…3ae0
    S-->>A: доставка: код активации, QR, статус-токен
    A->>O: QR и код активации, в обход модели
    Note over O,W: через 34 минуты
    O->>A: сделай возврат последней eSIM, я её не устанавливал
    A->>O: подтвердить esim_refund?
    O-->>A: /yes
    A->>S: POST /refund {esim_tran_no, status_token}
    S->>W: установлена? расход данных?
    W-->>S: GOT_RESOURCE, не установлена, 0 байт
    S->>W: отменить профиль
    S->>F: verify и settle 0.31 USDC, кошелёк продавца → ARGUS
    F-->>S: tx 0x6dcfb7f0…ed4b
    S-->>A: refunded
    A->>O: возвращено 0.31 USDC, tx 0x6dcfb7f0…ed4b

4. Транзакции

Всё в сети Base mainnet, в USDC (0x8335…2913). Любую можно открыть на basescan.org.

ШагТранзакцияБлок, время (UTC)Откуда → кудаСуммаГаз оплатил
Пополнение агента0x225afba5cd651e3ccdf70593fe985d1e24ddc14836270e83b13f546b6d01757852624834кошелёк владельца 0x097e…475a → ARGUS0.50владелец
Покупка0x617efd7abe4b4c6a80b54046617a73415aa54df7ada5f002ce7260cf68ac3ae052626137, 05:20:21ARGUS → кошелёк продавца0.31фасилитатор 0x93f6…be44
Возврат0x6dcfb7f075ad7fb6308064ac53e310dfb6adfd9b65d9f44b3c9a6dd39ca9ed4b52627173, 05:54:53кошелёк продавца → ARGUS0.31фасилитатор 0x4c93…0205

И покупка, и возврат — это вызовы EIP-3009 transferWithAuthorization: платящий кошелёк подписывает, фасилитатор отправляет. Ни у ARGUS, ни у кошелька продавца не было ETH — ни до, ни во время, ни после.

5. Деньги и балансы

flowchart LR
    A["Кошелёк ARGUS"] -- "покупка: 0.31 USDC (x402)" --> S["Кошелёк продавца"]
    S -- "возврат: 0.31 USDC (EIP-3009 через фасилитатор)" --> A
    N["Узел продавца"] -- "заказ на 0.30 USD, затем отмена" --> W["Баланс eSIM Access"]
    F["Фасилитатор x402"] -. "газ за оба перевода" .-> B["Base"]
ДоПосле покупкиПосле возврата
Кошелёк ARGUS0.50 USDC0.19 USDC0.50 USDC
Кошелёк продавца00.31 USDC0
Баланс eSIM Access$20.00$19.70$20.00
ETH, потраченный ARGUS или продавцом000

Стенд продавал по себестоимости (MARGIN_PCT=0, MIN_MARGIN_USD=0.01): $0.30 оптом, 0.31 USDC для агента. С наценкой кита по умолчанию тот же тариф стоит $1.30.

6. Правила возврата

stateDiagram-v2
    [*] --> delivered: оплачено, расчёт прошёл
    delivered --> in_use: установлена или есть расход данных
    in_use --> [*]: 409 in_use, без возврата
    delivered --> cancelled: POST /refund со статус-токеном
    cancelled --> refunded: кошелёк возвратов вернул цену
    cancelled --> due: кошелька возвратов нет или выплата не прошла
    due --> [*]: оператор платит вручную
    refunded --> [*]

7. Как включить возвраты на своём узле

Возвраты выключены, пока вы не дадите узлу кошелёк, из которого их платить. Без него POST /refund всё равно отменяет неиспользованную eSIM и записывает возврат как причитающийся, а вам приходит вебхук agent_order.refund_due, чтобы вы заплатили сами.

# кошелёк с USDC в Base для возвратов: сам кошелёк PAY_TO, тогда возвраты отдают пришедшие деньги,
# или отдельный резерв. ETH не нужен: газ платит фасилитатор.
cd ~/esim-operator-kit
umask 077
printf 'Refund wallet private key: '; read -rs v; printf %s "$v" > secrets/refund_key; echo; unset v
sudo chown 1000:1000 secrets/refund_key && sudo chmod 600 secrets/refund_key
echo "REFUND_KEY_FILE=/run/secrets/esim/refund_key" >> .env
echo "REFUND_MAX_USD=20" >> .env
echo "REFUND_DAILY_MAX_USD=100" >> .env
docker compose up -d rails
curl -s https://<your domain>/agents/healthz    # "refunds": "automatic"
НастройкаЧто делает
REFUND_KEY_FILEКлюч кошелька, из которого платятся возвраты. Единственный приватный ключ, который кит вообще читает, и только если вы это включили.
REFUND_MAX_USDМаксимум одного возврата.
REFUND_DAILY_MAX_USDМаксимум всех возвратов за сутки.
CDP_KEY_FILEУже задан для платежей; возвраты идут через тот же фасилитатор.

Если кошелёк возвратов — не ваш основной, держите на нём только резерв: ключ на сервере — это ключ, который можно прочитать при взломе.

8. Как попросить возврат

Агенту нужны два значения, полученные с доставкой:

curl -s -X POST https://<seller>/agents/refund -H 'content-type: application/json' \
  -d '{"esim_tran_no":"26101505200012","status_token":"…"}'
{"success": true, "result": {"esim_tran_no": "26101505200012", "status": "refunded", "amount_usd": "0.31",
 "to": "0x428f2be4327908948e3b1915c55ddf8fa6bf73cc", "at": "2026-10-15T05:54:50.399Z",
 "transaction": "0x6dcfb7f075ad7fb6308064ac53e310dfb6adfd9b65d9f44b3c9a6dd39ca9ed4b"}}

status — это refunded с транзакцией или due, когда продавец платит вручную. Какой вариант у продавца, видно в /listing.json: в refund.policy записано правило, а /healthz показывает "refunds": "automatic" или "operator".

9. Что мы узнали

10. Кейс 2: через хаб, у нашего публичного узла

В кейсе 1 агенту дали адрес продавца. В кейсе 2 он нашёл продавца сам: ARGUS поискал продавцов eSIM в хабе modelmarket.dev, получил нашу капабилити esim.quote@v1 продавца esim-modelmarket, запросил у неё предложения через хаб и заплатил по x402 на собственный /order продавца. Хаб провёл бесплатный запрос цены и не касался денег.

Для этого теста наш публичный узел перевели из демо в режим продаж, а сразу после — обратно в демо. Узел за esim-modelmarket (modelmarket.dev/providers/esim) продавал 52 минуты, с 06:56:55 до 07:48:33 UTC 15 октября 2026 года, по себестоимости (MARGIN_PCT=0, MIN_MARGIN_USD=0.01), принимая оплату на тот же кошелёк продавца, что и стенд, и автоматически возвращая из него (не больше $2 за возврат и $5 в сутки). С 07:48:33 он снова отклоняет каждый заказ с demo_mode.

sequenceDiagram
    autonumber
    actor O as Владелец (Telegram)
    participant A as ARGUS (агент)
    participant H as Хаб modelmarket.dev
    participant S as Узел продавца (modelmarket.dev/providers/esim)
    participant F as Фасилитатор x402
    O->>A: купи мне самую дешёвую eSIM в Турцию
    A->>H: GET /ai-market/v2/search?intent=esim
    H-->>A: esim.quote@v1 продавца esim-modelmarket (через esim.modelmarket.dev)
    A->>H: POST /ai-market/v2/invoke esim.quote@v1 (бесплатно)
    H->>S: передаёт запрос цены
    S-->>A: seller demo: false · TR_0.5_7 0.31 USDC · заказ на …/providers/esim/order
    A->>O: [SELLS] TR_0.5_7 0.31 USDC · подтвердить esim_buy?
    O-->>A: /yes
    A->>S: x402 напрямую продавцу: 402, затем PAYMENT-SIGNATURE (EIP-3009)
    S->>F: verify, затем settle
    F-->>S: tx 0xeea12962…881e
    S-->>A: delivery
    A->>O: QR и код активации, в обход модели
    O->>A: сделай возврат последней eSIM
    A->>O: подтвердить esim_refund?
    O-->>A: /yes
    A->>S: POST /refund {esim_tran_no, status_token}
    S->>F: отмена в eSIM Access, затем 0.31 USDC назад
    F-->>S: tx 0x45dc5ce6…ec88
    S-->>A: refunded
Время (UTC)Что произошло
06:56:55Публичный узел переходит из демо в продажи. Через хаб его ответ теперь говорит demo: false и 0.31 USDC
07:21Первая попытка: ARGUS видит предложения, но отказывается покупать. Узел всё ещё назывался «modelmarket.dev demo seller», и агент судил по имени
07:23Исправление выкачено: имя узла следует его режиму, а ARGUS помечает каждое предложение [SELLS] или [DEMO] по ответу самого продавца
07:47:35ARGUS покупает TR_0.5_7 после /yes владельца; eSIM 26101507470034 доставлена в Telegram владельца
07:48:02Владелец просит возврат и подтверждает /yes; узел отменяет неиспользованную eSIM и возвращает деньги
07:48:33Публичный узел переведён обратно в демо
ШагТранзакцияБлок, время (UTC)Откуда → кудаUSDCГаз оплатил
Покупка0xeea12962c4f494e55acc59a376203bd4b704804f19a84b4b8f47a96b265a881e52630556, 07:47:39ARGUS → кошелёк продавца 0xF471…bAE20.31фасилитатор 0x68a9…7863
Возврат0x45dc5ce6579d8e889750442d63773586c481a11b30ddf44805960860f3bbec8852630569, 07:48:05кошелёк продавца → ARGUS0.31фасилитатор 0x625d…ac39

ARGUS был единственным покупателем в это окно: в записях узла один заказ, и он возвращён. В конце у ARGUS снова 0.50 USDC, у кошелька продавца 0, баланс eSIM Access — $20.00, eSIM в состоянии CANCEL, и ни один кошелёк не потратил ETH.

Что показал этот кейс:

11. Кейс 3: два покупателя, и хаб считает доставки

Продавец, которому платят напрямую, для хаба невидим: деньги идут от агента к продавцу, а хаб видит только бесплатный запрос цены. Поэтому для хаба продавец, который берёт деньги и ничего не доставляет, выглядел так же, как тот, что доставляет. С 15 октября 2026 года узел продавца подписывает квитанцию на каждую доставку и каждый возврат, и покупатель может принести её в хаб вместе с транзакцией. Хаб проверяет подпись и перевод ончейн и засчитывает подтверждённую доставку в листинг продавца. Кейс 3 проверил это от начала до конца с двумя разными покупателями.

Для этого теста наш публичный узел в третий раз перевели из демо в режим продаж, а сразу после — обратно в демо. Он продавал 9 минут, с 09:38:59 до 09:48:22 UTC 15 октября 2026 года, на тех же условиях, что в кейсе 2: по себестоимости, на тот же кошелёк продавца, с автоматическими возвратами не больше $2 за возврат и $5 в сутки. С 09:48:22 он снова отклоняет каждый заказ с demo_mode (403).

ПокупательКто этоКошелёк
Claude Codeагент для разработки в терминале владельца. Он запустил пример покупателя из кита rails/examples/agent-buy.mjs; скрипт прочитал ключ из файла, сам агент ключа не видел0x097e3F339D0b023605e12A6B81E2d6Cb7571475a
ARGUSагент владельца в Telegram, как в кейсах 1 и 2. Покупку и возврат владелец подтвердил командой /yes0x428f2Be4327908948e3B1915C55ddF8fA6bf73cc

11.1 Покупка из Claude Code

Вся покупка — одна команда. Без --yes она только запрашивает цены; с --refund сразу после доставки просит деньги назад.

cd rails
node examples/agent-buy.mjs TR --hub https://modelmarket.dev --key-file ~/.aicom-pov-buyer.json --yes --refund
seller   modelmarket.dev eSIM seller (https://modelmarket.dev → https://esim.modelmarket.dev)

offer    TR_0.5_7 — Turkey 500MB 7Days — 0.31 USDC, from modelmarket.dev eSIM seller
order at https://modelmarket.dev/providers/esim/order
payer    0x097e3F339D0b023605e12A6B81E2d6Cb7571475a

delivered  esim_tran_no 26101509410001 · iccid 8997…7746 · apn internet
activation LPA:1$rsp-eu.s… (the traveller's secret)
paid       0x85d355853807967e85b1efc3f15261e0c58006091898cb98d46095db07bc103e
hub        delivery counted: {"confirmed":1,"distinct_buyers":1,"refunded":0}

refund     refunded · 0.31 USDC to 0x097e3f339d0b023605e12a6b81e2d6cb7571475a · 0x3313e8be7726ce1e3bc4dcf95afde0bd5eb3de0c8a57b601f8b3aaf86ed85c00
hub        refund counted: {"confirmed":1,"distinct_buyers":1,"refunded":1}

Скрипт нашёл продавца через хаб, пропустил продавцов в демо-режиме, взял самое дешёвое предложение, заплатил по x402 с лимитом $1 на платёж и отнёс обе квитанции в хаб. Через три минуты ARGUS купил тот же тариф в Telegram, и счётчик дошёл до двух покупателей.

11.2 Цепочка с квитанциями

sequenceDiagram
    autonumber
    participant B as Покупатель (agent-buy.mjs или ARGUS)
    participant H as Хаб modelmarket.dev
    participant S as Узел продавца
    participant C as Base
    B->>H: поиск intent=esim, затем esim.quote@v1 (бесплатно)
    H->>S: передаёт запрос цены
    S-->>B: [SELLS] TR_0.5_7 · 0.31 USDC · адрес заказа
    B->>S: заказ по x402: авторизация EIP-3009 с nonce N1
    S-->>B: доставка + квитанция о доставке {payer, pay_to, nonce N1}, подписанная ключом продавца
    B->>H: POST /ai-market/v2/reputation/deliveries {receipt, signature, transaction}
    H->>H: подпись против provider_pubkey, опубликованного в листинге продавца
    H->>C: есть подтверждённый перевод под nonce N1 от плательщика на pay_to?
    C-->>H: да
    H-->>B: засчитано: deliveries_30d
    B->>S: POST /refund {esim_tran_no, status_token}
    S-->>B: refunded + квитанция о возврате {refund_from, refund_nonce N2}
    B->>H: квитанция о возврате и её транзакция
    H->>C: есть перевод под nonce N2 с кошелька продавца плательщику?
    H-->>B: засчитано: refunded +1
Время (UTC)Что произошлоСчётчик в листинге после
09:38:59Публичный узел переходит из демо в режим продажпока пусто
09:41:05Claude Code платит за TR_0.5_7; eSIM 26101509410001 доставлена1 доставка, 1 покупатель, 0 возвратов
09:41:19Деньги за неё возвращены, eSIM отменена1, 1, 1
09:44:19ARGUS платит после /yes владельца; eSIM 26101509440019 уходит владельцу в Telegram2, 2, 1
09:44:53Возврат ARGUS выплачен после /yes2, 2, 2
09:48:22Публичный узел переведён обратно в демо2, 2, 2 (хранится 30 дней)

11.3 Транзакции

ШагТранзакцияБлок, время (UTC)Откуда → кудаUSDCГаз оплатил
Покупка, Claude Code0x85d355853807967e85b1efc3f15261e0c58006091898cb98d46095db07bc103e52633959, 09:41:050x097e…475a → кошелёк продавца 0xF471…bAE20.31фасилитатор 0xca5e…c70d
Возврат, Claude Code0x3313e8be7726ce1e3bc4dcf95afde0bd5eb3de0c8a57b601f8b3aaf86ed85c0052633966, 09:41:19кошелёк продавца → 0x097e…475a0.31фасилитатор 0x93f6…be44
Покупка, ARGUS0xf9ac406f3e329ac2c4c02e26562b6fb944e4165b71b88c4a0756a193325f966952634056, 09:44:19ARGUS → кошелёк продавца0.31фасилитатор 0x93f6…be44
Возврат, ARGUS0x5fa5da5455226a20d10dc84ffb8adf56b01d972dcc72f8e135b4a507a8c3528752634073, 09:44:53кошелёк продавца → ARGUS0.31фасилитатор 0x8f5c…e531

В записях узла за это окно ровно эти два заказа, оба возвращены. В конце у обоих покупателей было то же, что до теста (0.594148 и 0.50 USDC), у кошелька продавца 0, баланс eSIM Access — $20.00, обе eSIM в состоянии CANCEL с 0 байт трафика, и ни один кошелёк не потратил ETH.

11.4 Квитанция и что проверяет хаб

Квитанция о доставке для покупки ARGUS в том виде, в каком её подписывает узел. Она называет платёж, а не eSIM: кода активации, ICCID и статус-токена в ней нет.

{"v": 1, "kind": "delivery", "capability": "esim.order@v1", "product_id": "esim-modelmarket", "chain_id": 8453,
 "payer": "0x428f2be4327908948e3b1915c55ddf8fa6bf73cc", "pay_to": "0xF47161fBB56D0D910a17e503C8292903F41BbAE2",
 "nonce": "0xddde4ccd3b8d8ba361b94985b0b063f50ae41f43217cfc3ccadc2d636201f79e", "offer_id": "TR_0.5_7",
 "at": "2026-10-15T09:44:…Z"}

Подпись — Ed25519 над каноническим JSON квитанции (ключи по алфавиту, без пробелов), тем же ключом продавца, которым узел подписывает каждый бесплатный ответ. В квитанции о возврате kind: "refund", refund_from (кошелёк, который вернул деньги), refund_nonce (nonce EIP-3009 этого перевода) и delivery_nonce.

flowchart TD
    R["квитанция + подпись + транзакция"] --> K{"подписано ключом provider_pubkey<br/>из листинга на этом хабе?"}
    K -- нет --> E404["404: такого продавца нет"]
    K -- да --> T{"на Base: перевод USDC под nonce квитанции<br/>от плательщика на pay_to<br/>(возврат: с refund_from плательщику)?"}
    T -- "ещё не подтверждён" --> E422["422: повторите через несколько секунд"]
    T -- нет --> E422b["422: транзакция не подтверждает квитанцию"]
    T -- да --> D{"эта транзакция уже засчитана?"}
    D -- да --> SAME["200, recorded: false"]
    D -- нет --> OK["200, recorded: true: deliveries_30d +1"]

11.5 Где мы сейчас

Что показал этот кейс:

Кит на GitHub →