@rozoai/checkout 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,269 +1,243 @@
1
1
  # rozo-checkout
2
2
 
3
- **English** | [简体中文](README.zh.md) | [日本語](README.ja.md) | [Español](README.es.md)
3
+ **English** | [简体中文](docs/README.zh.md) | [日本語](docs/README.ja.md) | [Español](docs/README.es.md)
4
4
 
5
- **[Quick start →](QUICKSTART.md)** — pay a link in five minutes, without reading any of this.
5
+ Pay an **OpenRouter Coinbase Payment Link** with a coin that link cannot take
6
+ directly — BTC over Lightning, or USDT/USDC on Solana, BNB Chain, Ethereum,
7
+ Polygon, Base or Stellar. A Coinbase Payment Link only accepts USDC on Base;
8
+ this routes the coin you actually hold through a bridge, and a funder wallet
9
+ settles the invoice for you. No account, no API key, no browser.
10
+
11
+ ```bash
12
+ npx @rozoai/checkout pay <coinbase-link>
13
+ ```
14
+
15
+ It asks which coin you want to pay with — paste your wallet address at the
16
+ prompt and it will mark which coins you can actually afford — then prints a
17
+ deposit address for you to pay from any wallet — **no private key, no environment variable, no
18
+ configuration** — and waits until the invoice is settled.
19
+
20
+ Know your coin already? Skip the question:
6
21
 
7
22
  ```bash
8
23
  npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
9
24
  ```
10
25
 
11
- Pay an **OpenRouter Coinbase Payment Link** with a coin that link cannot take
12
- directly — BTC over Lightning, or USDT/USDC on Solana, BNB Chain, Ethereum,
13
- Polygon, Base or Stellar.
14
-
15
- A Coinbase Payment Link only accepts USDC on Base. This repo is an agent skill
16
- (plus the Node scripts behind it) that routes any of the coins above through a
17
- bridge: you get a one-time deposit address for the coin you actually hold, and
18
- once your deposit lands a funder wallet settles the Coinbase invoice on your
19
- behalf.
20
-
21
- On the invoice itself there is **no discount**: `callerPays` equals the invoice
22
- amount. The **deposit** you send is a different number, and it is normally
23
- larger — it includes the bridge and source-chain fees needed to deliver the
24
- invoice amount in Base USDC. Always send exactly the `deposit.amount` the
25
- backend returns; never assume it equals the invoice.
26
-
27
- - `SKILL.md` — the agent-facing instructions (Claude Code skill format).
28
- - `llms.txt` — a compact summary for agents that read one file.
29
- - `scripts/` — the Node implementation; `src/` is the source, `dist/` holds
30
- self-contained bundles you can run with plain `node`.
31
- - `test/` — offline unit tests for the money-handling and safety logic.
32
- - `PLAN.md` — the design document the implementation follows.
33
-
34
- You do **not** need an account, an API key, or any relationship with the
35
- operator to use this. Every endpoint it calls is public and keyless.
36
-
37
- ## How it works
38
-
39
- ```mermaid
40
- flowchart TD
41
- A["Coinbase Payment Link<br/>payments.coinbase.com/payment-links/pl_*"] --> B
42
- B["quote-invoice<br/>(public POST)"] --> C["create-invoice<br/>(public POST)"]
43
- C --> D["Bridge order<br/>one-time deposit address<br/>+ exact amount + expiry"]
44
- D --> E["You send USDT/USDC/BTC<br/>on your chosen chain"]
45
- E --> F["Bridge converts the pay-in"]
46
- F --> G["Funder wallet settles<br/>the Coinbase invoice"]
47
- G --> H["Merchant is paid<br/>(e.g. OpenRouter credit)"]
26
+ ## Coins you can pay with
27
+
28
+ | Chain | `--with` | Chain id | Notes |
29
+ |---|---|---|---|
30
+ | Ethereum | `usdt-ethereum` `usdc-ethereum` | `1` | 6 decimals |
31
+ | BNB Chain | `usdt-bnb` `usdc-bnb` | `56` | 18 decimals |
32
+ | Polygon | `usdt-polygon` `usdc-polygon` | `137` | 6 decimals |
33
+ | Base | `usdc-base` | `8453` | 6 decimals |
34
+ | Solana | `usdt-solana` `usdc-solana` | `900` | SPL; native SOL not supported |
35
+ | Stellar | `usdc-stellar` | `1500` | memo required — shown in the deposit block |
36
+ | Bitcoin Lightning | `btc-lightning` | `lightning` | BOLT11; amounts in satoshis |
37
+
38
+ Native gas coins (SOL, BNB, ETH, MATIC) and on-chain BTC are not accepted.
39
+
40
+ ## Use it from your agent
41
+
42
+ The payload is the same everywhere: the one-liner above, or point the agent at
43
+ [llms.txt](llms.txt). Agents and scripts should always pass `--with` — the
44
+ picker only appears on a terminal, and there is deliberately no default coin. **Paying from your own wallet never needs a key.** Only
45
+ the optional `--send` flag signs locally, and only that flag reads
46
+ `ROZO_CHECKOUT_EVM_KEY` / `ROZO_CHECKOUT_SOL_KEY`.
47
+
48
+ <details>
49
+ <summary><b>Claude Code</b> — install the skill, or paste the one-liner</summary>
50
+
51
+ This repo is a Claude Code skill: it ships `SKILL.md` plus the executables in
52
+ `scripts/dist/`. Clone it into your skills directory and Claude Code picks it
53
+ up automatically.
54
+
55
+ ```bash
56
+ git clone https://github.com/RozoAI/rozo-checkout-skill ~/.claude/skills/rozo-checkout
48
57
  ```
49
58
 
50
- The same thing as ASCII, for terminals without mermaid:
59
+ Or skip the install and just ask it to run:
51
60
 
52
61
  ```
53
- Coinbase Payment Link (pl_* / paymentSession_*)
54
- |
55
- v
56
- [ quote-invoice ] -> merchant, amount, expiry, short-lived quote receipt
57
- |
58
- v
59
- [ create-invoice ] -> bridge order: rozoPaymentId + deposit address
60
- | + exact amount + order expiry
61
- v
62
- you send USDT / USDC / BTC on your chain ------> deposit address
63
- |
64
- v
65
- bridge converts the pay-in ------> funder wallet pays the Coinbase invoice
66
- |
67
- v
68
- merchant credited; poll until the state is `settled`
62
+ Pay this OpenRouter link with USDT on Solana:
63
+ npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
69
64
  ```
70
65
 
71
- Three identifiers appear throughout and are never interchangeable:
66
+ Wallet: any wallet, no key. Add `--send` only if you want Claude to sign from a
67
+ hot wallet, which needs the env key.
68
+ </details>
72
69
 
73
- | Identifier | What it is |
74
- |---|---|
75
- | `linkId` | the Coinbase id: `pl_*` (Payment Link) or `paymentSession_*` (v3 session) |
76
- | `rozoPaymentId` | the bridge order's UUID — use this for deposit detail and status |
77
- | `paymentLink` | a hosted pay page URL for the bridge order (human fallback) |
70
+ <details>
71
+ <summary><b>Codex CLI</b> — AGENTS.md, or run it directly</summary>
78
72
 
79
- ## Supported sources
73
+ Codex reads `AGENTS.md` from the project root. Add a standing instruction so it
74
+ knows how to pay without being told each time:
80
75
 
81
- | Chain | Chain id | Tokens | Notes |
82
- |---|---|---|---|
83
- | Ethereum | `1` | USDC, USDT | 6 decimals |
84
- | BNB Chain | `56` | USDC, USDT | **18 decimals** — the usual source of off-by-10^12 bugs |
85
- | Polygon | `137` | USDC, USDT | 6 decimals |
86
- | Base | `8453` | USDC | 6 decimals |
87
- | Solana | `900` | USDC, USDT | 6 decimals; SPL, may require a memo. Native SOL is **not** supported |
88
- | Stellar | `1500` | USDC | 7 decimals; requires the memo |
89
- | Bitcoin Lightning | `lightning` | BTC | amounts are integer **satoshis**, paid via a BOLT11 invoice |
90
-
91
- Native gas coins (SOL, BNB, ETH, MATIC) and on-chain BTC are not accepted.
76
+ ```
77
+ To pay an OpenRouter / Coinbase payment link, run:
78
+ npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
79
+ ```
92
80
 
93
- ## Quickstart
81
+ Wallet: any wallet, no key. `--send` needs the env key.
82
+ </details>
94
83
 
95
- ### 1. Try the public endpoints with curl
84
+ <details>
85
+ <summary><b>OpenCode</b> — AGENTS.md, or run it directly</summary>
96
86
 
97
- Replace `pl_01YOURLINKID` with a real Coinbase Payment Link. No auth header is
98
- needed anywhere below.
87
+ OpenCode also reads `AGENTS.md` from the project root, so the Codex snippet
88
+ above works unchanged. The shortest path is still the command itself:
99
89
 
100
90
  ```bash
101
- MPP="https://apiserver.mpprouter.dev/v1/services/rozo-agent-api"
102
- INTENTS="https://intentapiv4.rozo.ai/functions/v1/payment-api"
103
- LINK="https://payments.coinbase.com/payment-links/pl_01YOURLINKID"
91
+ npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
92
+ ```
93
+
94
+ Wallet: any wallet, no key. `--send` needs the env key.
95
+ </details>
96
+
97
+ <details>
98
+ <summary><b>Cline</b> — .clinerules, or run it directly</summary>
99
+
100
+ Cline reads standing instructions from `.clinerules` in the project root:
101
+
102
+ ```
103
+ To pay an OpenRouter / Coinbase payment link, run:
104
+ npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
105
+ ```
106
+
107
+ Wallet: any wallet, no key. `--send` needs the env key.
108
+ </details>
104
109
 
105
- # Quote it: merchant, amount, expiry, and a ~60-second quoteReceipt.
106
- curl -s -X POST "$MPP/quote-invoice" \
107
- -H 'content-type: application/json' \
108
- -d "{\"url\":\"$LINK\"}"
110
+ <details>
111
+ <summary><b>Cursor</b> — .cursor/rules, or run it directly</summary>
109
112
 
110
- # Create a bridge order for, say, USDT on Solana.
111
- # This creates an order but moves no money; an unfunded order simply expires.
112
- curl -s -X POST "$MPP/create-invoice" \
113
- -H 'content-type: application/json' \
114
- -d "{\"url\":\"$LINK\",\"source\":{\"chainId\":\"900\",\"tokenSymbol\":\"USDT\"}}"
113
+ Add a project rule at `.cursor/rules/rozo-checkout.mdc`:
115
114
 
116
- # Deposit instructions (authoritative), using the rozoPaymentId from above.
117
- curl -s "$INTENTS/payments/<rozoPaymentId>"
115
+ ```
116
+ To pay an OpenRouter / Coinbase payment link, run:
117
+ npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
118
+ ```
118
119
 
119
- # Fulfilment status, using the Coinbase linkId.
120
- curl -s "$MPP/invoice-status?payment_id=pl_01YOURLINKID"
120
+ Wallet: any wallet, no key. `--send` needs the env key.
121
+ </details>
122
+
123
+ <details>
124
+ <summary><b>Hermes Agent</b> — run the one-liner in a session</summary>
125
+
126
+ Hermes Agent (Nous Research) has shell access and its own skill system. Start it
127
+ with `hermes` and ask:
128
+
129
+ ```
130
+ Fetch https://checkout.rozo.ai/llms.txt, then pay this OpenRouter link:
131
+ npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
121
132
  ```
122
133
 
123
- `create-invoice` is rate-limited per IP (about 30/hour); the read endpoints are
124
- not.
134
+ Wallet: any wallet, no key. `--send` needs the env key.
135
+ </details>
125
136
 
126
- ### 2. Use the CLI
137
+ <details>
138
+ <summary><b>OpenClaw</b> — openclaw agent exec</summary>
127
139
 
128
- Nothing to install — `npx` fetches and runs it:
140
+ OpenClaw's headless entry point runs a one-off task, which suits a payment you
141
+ trigger from a script or a chat channel:
129
142
 
130
143
  ```bash
131
- npx @rozoai/checkout quote <coinbase-link>
132
- npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
133
- npx @rozoai/checkout status <rozoPaymentId>
144
+ openclaw agent exec "Pay this OpenRouter link with USDT on Solana by running: npx @rozoai/checkout pay <coinbase-link> --with usdt-solana"
134
145
  ```
135
146
 
136
- `pay` walks the whole flow: quote, create the order, show a masked review, ask
137
- for a yes, then print the deposit instructions and poll until settlement. Add
138
- `--send` to pay from a hot wallet instead of your own, `--json` for machine
139
- output, and `--help` for everything else.
147
+ Wallet: any wallet, no key. `--send` needs the env key.
148
+ </details>
140
149
 
141
- ### 3. Or run the scripts directly
150
+ <details>
151
+ <summary><b>Pi</b> — run the one-liner in a session</summary>
142
152
 
143
- Cloning the repo gives you the same flows as individual scripts — this is what
144
- the agent skill uses, and what the CLI calls underneath.
153
+ Pi is a BYOK terminal agent whose built-in tools include `bash`, so it can run
154
+ the command directly. Start it with `pi` and ask:
145
155
 
146
- Each script prints exactly one JSON object on stdout. Exit `0` success, `1`
147
- refused/failed (read `error.code`), `2` usage, `3` submitted but unconfirmed.
156
+ ```
157
+ Pay this OpenRouter link with USDT on Solana by running:
158
+ npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
159
+ ```
160
+
161
+ Wallet: any wallet, no key. `--send` needs the env key.
162
+ </details>
163
+
164
+ <details>
165
+ <summary><b>Terminal — no agent at all</b> — run the scripts step by step</summary>
166
+
167
+ Drive each step yourself. The bundles are self-contained; nothing to install
168
+ beyond Node 18+.
148
169
 
149
170
  ```bash
150
- # Step 1 — read-only quote, costs nothing
171
+ git clone https://github.com/RozoAI/rozo-checkout-skill && cd rozo-checkout-skill
172
+ LINK="https://payments.coinbase.com/payment-links/pl_01YOURLINKID"
173
+
174
+ # Read-only quote, costs nothing
151
175
  node scripts/dist/quote.js --url "$LINK"
152
176
 
153
- # Step 2 — create the order (no money moves; unfunded orders expire).
154
- # The full deposit address is WITHHELD at this stage: you get the
155
- # masked summary to review, and `depositWithheld: true`.
177
+ # Create the order. The full deposit address is WITHHELD here; you get a
178
+ # masked summary to review first.
156
179
  node scripts/dist/create-order.js --url "$LINK" --chain 900 --token USDT
157
180
 
158
- # Step 3 — review the amount, chain, masked address, memo requirement and
159
- # expiry. Only when you have decided to pay, re-run the same command
160
- # with --confirm. This releases the full deposit block and records the
161
- # confirmation the send scripts require.
181
+ # Once you have decided to pay, re-run with --confirm to release it
162
182
  node scripts/dist/create-order.js --url "$LINK" --chain 900 --token USDT --confirm
163
183
 
164
- # Step 4a — Mode A: pay the deposit block from your own wallet,
165
- # then watch it settle
166
- node scripts/dist/status.js --rozo-payment-id <uuid> --watch --timeout 600
167
-
168
- # Step 4b — Mode B: let the script pay from a hot wallet. --dry-run signs
169
- # nothing; a real send additionally requires --send.
170
- ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
171
- node scripts/dist/send-sol.js --rozo-payment-id <uuid> --dry-run
184
+ # Pay the deposit block from any wallet, then watch it settle
185
+ node scripts/dist/status.js --rozo-payment-id <uuid> --watch
172
186
  ```
173
187
 
174
- `scripts/dist/*.js` are self-contained bundles — no `npm install` is needed at
175
- the call site. The CLI above is the same code with a friendlier surface: it
176
- imports these flows rather than reimplementing them, so every check below
177
- applies identically whichever entry point you use.
188
+ Each script prints exactly one JSON object on stdout. Exit `0` success, `1`
189
+ refused/failed (read `error.code`), `2` usage, `3` submitted but unconfirmed.
190
+ Full walkthrough: [QUICKSTART](docs/QUICKSTART.md).
178
191
 
179
- ## Build and test
192
+ Wallet: any wallet, no key. For hot-wallet sending see `send-evm.js` /
193
+ `send-sol.js`, which read `ROZO_CHECKOUT_EVM_KEY` / `ROZO_CHECKOUT_SOL_KEY`.
194
+ </details>
180
195
 
181
- ```bash
182
- npm install # only needed to rebuild or to run the tests
183
- npm run build # esbuild -> scripts/dist/*.js (node18 target) + blacklist.json
184
- npm test # node:test, fully offline
185
- npm run check # build + test
196
+ <details>
197
+ <summary><b>Any other agent</b> — point it at llms.txt</summary>
198
+
199
+ Any agent that can fetch a URL and run a command can do this:
200
+
201
+ ```
202
+ Fetch https://checkout.rozo.ai/llms.txt into your context, then use it
203
+ to pay this OpenRouter link: <coinbase-link>
186
204
  ```
187
205
 
188
- Tests make **no network calls**; every backend response is a fixture in
189
- `test/fixtures/`. They cover the atomic-amount conversion (6/18 decimals and
190
- Lightning satoshis), the expiry-margin arithmetic, compromised-address
191
- normalization and fail-closed behaviour, the order reuse decision, the
192
- post-create verification comparator, and the deposit-completeness rules.
193
-
194
- Two groups spawn real child processes rather than calling functions, because
195
- they test things a single-process test cannot: the concurrency suite races
196
- several processes to claim one order (exactly one may win) and to exhaust the
197
- session cap, and the entry-point suite runs the built send scripts to prove
198
- they refuse without `--send`, without a confirmation, and after a prior claim.
199
-
200
- ## Safety design
201
-
202
- The interesting part of this repo is what it refuses to do.
203
-
204
- - **Two-phase confirmation, enforced.** `create-order.js` withholds the full
205
- deposit address, memo and BOLT11 until it is re-run with `--confirm`, which
206
- records a confirmation bound to a sha256 of those exact instructions. The
207
- send scripts refuse without both `--send` and a confirmation whose digest
208
- still matches the live data, so neither an accidental invocation nor a
209
- swapped deposit address can move funds.
210
- - **Full invoice, always.** `callerPays` must equal the invoice amount and
211
- `discount` must be `"0"`; anything else aborts with `NO_DISCOUNT_VIOLATION`.
212
- Security-critical fields (`linkId`, `merchant`, `original`, `callerPays`, the
213
- echoed source) must be present as well as equal — a missing field is drift.
214
- - **Reuse guard.** Creating an order for a link that already has an unexpired
215
- order returns that existing order — even if it has already been funded. So on
216
- every run the live order is required to be unpaid (`payment_unpaid`, no tx
217
- hash, no amount received, no confirmation) and to match the chain and token
218
- the caller chose. Otherwise: `ORDER_ALREADY_FUNDED` or
219
- `REUSED_SOURCE_MISMATCH`.
220
- - **Money-detected rule, fail closed.** Once any pay-in exists, the tooling
221
- never reports a plain failure, never advises paying again, and never retries
222
- into a new order. An `amountReceived` that is non-null but unreadable counts
223
- as money, not as absence of money. An unreadable backend reports `unknown`,
224
- never `awaiting_deposit`.
225
- - **Complete deposit instructions.** A zero, negative or unparsable amount
226
- aborts. Lightning requires the BOLT11 (which arrives in `source.lnInvoice`
227
- with an empty address). Stellar requires its memo — a missing memo is a hard
228
- abort, never rendered as "no memo required".
229
- - **Expiry margins.** Payment is refused unless the earlier of the order expiry
230
- and the Coinbase expiry is more than a per-chain margin away (10 min EVM and
231
- Stellar, 5 min Solana). Lightning additionally requires at least 10 minutes
232
- of BOLT11 validity. A missing or unparsable deadline aborts.
233
- - **Payability revalidation.** A quote receipt makes order creation skip the
234
- live Coinbase check, and the link can be consumed by someone else at any
235
- moment — so payability is re-checked immediately before the deposit address
236
- is shown, and again as the very last step before broadcast, after all the RPC
237
- preparation. Incomplete Coinbase state is treated as "cannot prove payable",
238
- not as payable.
239
- - **Compromised-address list, fail closed.** `scripts/src/lib/blacklist.json`
240
- carries a vendored list with a provenance header and a sha256 over the
241
- addresses. The digest proves only that this vendored copy has not been edited
242
- since its sync date; it is not a signature by the upstream source. Both the
243
- deposit address and the sending wallet are checked. If the file is missing,
244
- malformed, empty, or its digest does not match, every send is refused rather
245
- than proceeding unchecked.
246
- - **Send-once, across processes.** Order state lives in
247
- `$HOME/.rozo-checkout/state/<uuid>.json`, written atomically (temp file,
248
- fsync, rename). Every read-modify-write of a state file — the claim, the
249
- spend caps, the order record and the confirmation — runs inside one exclusive
250
- lockfile, so two concurrent invocations can neither both decide they are
251
- first, nor overwrite each other's send record. A send is claimed *before* broadcasting, so an ambiguous RPC error can
252
- never become a second transfer. Transactions are signed before broadcast so
253
- the hash is known in advance; on an ambiguous result the scripts look that
254
- exact transaction up instead of rebroadcasting.
255
- - **Hot-wallet controls.** Keys come from the environment only
256
- (`ROZO_CHECKOUT_EVM_KEY`, `ROZO_CHECKOUT_SOL_KEY`), are never printed and
257
- never accepted on the command line; library and RPC errors are redacted
258
- before display, including credential-bearing provider URLs, bearer tokens and
259
- key-shaped strings. The scripts refuse to run when any `.env`/`.env.*` in the
260
- working directory is git-tracked, and refuse just as hard when git cannot
261
- prove it is untracked. The RPC's chain id (or Solana genesis hash) and the token's
262
- on-chain decimals are verified before signing. Caps: $100 per transaction,
263
- $200 cumulative per session.
264
- - **Address masking.** Prose shows `first6...last4`. The full deposit address,
265
- memo and BOLT11 string appear only inside the machine-readable `deposit`
266
- object, so they stay copy-pastable without being scattered through logs.
206
+ If the agent has no shell but can make HTTP requests, it can drive the four
207
+ public endpoints directly — see [how it works](docs/how-it-works.md).
208
+
209
+ Wallet: any wallet, no key. `--send` needs the env key.
210
+ </details>
211
+
212
+ ## Three rules worth knowing
213
+
214
+ - **The deposit address is one-time.** Never reuse one from an older order, a
215
+ cached response or a screenshot.
216
+ - **Send the exact amount shown.** It is normally larger than the invoice — it
217
+ includes the bridge and network fees.
218
+ - **Never pay a funded order twice.** If a payment has already been detected,
219
+ stop and get a human to reconcile it; a second payment to a one-time address
220
+ is not guaranteed to be credited.
221
+
222
+ The full list of what this refuses to do, and why, is in
223
+ [docs/safety.md](docs/safety.md).
224
+
225
+ ## Links
226
+
227
+ - [Quick start](docs/QUICKSTART.md) — the five commands, with expected output
228
+ - [How it works](docs/how-it-works.md) — the flow, the endpoints, the identifiers
229
+ - [Safety design](docs/safety.md) — every rail, in detail
230
+ - [SKILL.md](SKILL.md) — agent-facing instructions · [llms.txt](llms.txt) — one-file summary
231
+ - [checkout.rozo.ai/agent](https://checkout.rozo.ai/agent.html) — the same thing on the web
232
+ - [Issues](https://github.com/RozoAI/rozo-checkout-skill/issues) — bugs and requests
233
+
234
+ ## Changelog
235
+
236
+ - **0.1.1** — one spend limit instead of two: a single payment may not exceed
237
+ $1,100 (sized for a $1,000 credit purchase plus its 5% fee), the cumulative
238
+ session cap and the `--yes-large` override are removed. Docs make it explicit
239
+ that paying from your own wallet needs no key or configuration.
240
+ - **0.1.0** — first release: `npx @rozoai/checkout`.
267
241
 
268
242
  ## License
269
243
 
@@ -5,22 +5,35 @@
5
5
  Pagar un enlace de pago de Coinbase (Coinbase Payment Link) de OpenRouter con
6
6
  USDT/USDC en Solana, BNB Chain, Ethereum, Polygon, Base o Stellar, o con BTC por
7
7
  Lightning. Cinco minutos. Para saber cómo funciona y por qué, ver
8
- [README.md](README.md).
8
+ [README.md](../README.md).
9
9
 
10
10
  ## El comando de una sola línea
11
11
 
12
+ ```bash
13
+ npx @rozoai/checkout pay https://payments.coinbase.com/payment-links/pl_01YOURLINKID
14
+ ```
15
+
16
+ Eso ejecuta por uno todos los pasos de abajo: elegir moneda, cotizar, crear,
17
+ revisar, confirmar, instrucciones de depósito y luego consultar hasta la
18
+ liquidación. En el paso de elegir moneda se puede pegar la dirección de la
19
+ billetera y el selector consultará los saldos y marcará cuáles se pueden pagar
20
+ —es opcional y nunca cambia lo que se firma—.
21
+
22
+ Si ya se sabe qué moneda usar, se puede indicar y omitir la pregunta:
23
+
12
24
  ```bash
13
25
  npx @rozoai/checkout pay https://payments.coinbase.com/payment-links/pl_01YOURLINKID --with usdt-solana
14
26
  ```
15
27
 
16
- Eso ejecuta por uno todos los pasos de abajo: cotizar, crear, revisar, confirmar,
17
- instrucciones de depósito y luego consultar hasta la liquidación. Monedas para
18
- `--with`: `usdt-solana`, `usdc-solana`, `usdt-bnb`, `usdc-bnb`, `usdt-ethereum`,
28
+ Monedas para `--with`: `usdt-solana`, `usdc-solana`, `usdt-bnb`, `usdc-bnb`, `usdt-ethereum`,
19
29
  `usdc-ethereum`, `usdt-polygon`, `usdc-polygon`, `usdc-base`, `usdc-stellar`,
20
- `btc-lightning`.
30
+ `btc-lightning`. Los scripts y los agentes deben pasar siempre `--with`: el
31
+ selector solo aparece en una terminal y no hay moneda por defecto.
21
32
 
22
- Añadir `--send` para pagar desde una billetera caliente en lugar de la propia, y
23
- `--json` para obtener una salida legible por máquina.
33
+ Por defecto solo imprime una dirección para pagar desde cualquier billetera: sin
34
+ clave privada y sin configuración. Añadir `--send` únicamente si se quiere que la
35
+ CLI firme desde una billetera caliente, y `--json` para obtener una salida
36
+ legible por máquina.
24
37
 
25
38
  El resto de esta página es el mismo flujo ejecutado paso a paso, que es lo que
26
39
  conviene si algo sale mal o si se quiere automatizar por cuenta propia.
@@ -54,8 +67,8 @@ node scripts/dist/quote.js --url "$LINK"
54
67
  {
55
68
  "success": true,
56
69
  "merchant": "OpenRouter, Inc.",
57
- "invoice": { "amount": "5.00", "fiat": { "amount": "5.00", "currency": "USD" } },
58
- "callerPays": "5.00",
70
+ "invoice": { "amount": "1050.00", "fiat": { "amount": "1050.00", "currency": "USD" } },
71
+ "callerPays": "1050.00",
59
72
  "coinbaseExpiryIso": "2026-08-09T10:00:00.000Z"
60
73
  }
61
74
  ```
@@ -77,19 +90,21 @@ resumen enmascarado para revisarlo primero.
77
90
  {
78
91
  "success": true,
79
92
  "rozoPaymentId": "11111111-2222-4333-8444-555555555555",
80
- "invoice": { "amount": "5.000000", "currency": "USD" },
93
+ "invoice": { "amount": "1050.000000", "currency": "USD" },
81
94
  "deposit": null,
82
95
  "depositWithheld": true,
83
96
  "display": {
84
97
  "chain": "Solana",
85
- "amount": "5.021000 USDT",
86
- "payToMasked": "9WzDXw...AWWM",
87
- "memoRequirement": "This deposit REQUIRES the memo/tag below. ..."
98
+ "amount": "1054.410000 USDT",
99
+ "payToMasked": "9WzDXw...AWWM"
88
100
  },
89
101
  "expiry": { "effectiveDeadlineIso": "2026-08-08T11:00:00.000Z", "minutesOfSlack": 55 }
90
102
  }
91
103
  ```
92
104
 
105
+ Este ejemplo es el caso insignia: una factura de **$1,050.00** por $1,000 de
106
+ créditos de OpenRouter. Cualquier factura de hasta **$1,100** se puede pagar así.
107
+
93
108
  **Revisar `display.amount` antes de continuar.** Normalmente es mayor que la
94
109
  factura: incluye las comisiones del puente (bridge) y de la red. Anotar el
95
110
  `rozoPaymentId`; todos los comandos posteriores lo usan.
@@ -114,23 +129,38 @@ exigen los scripts de envío.
114
129
  "tokenSymbol": "USDT",
115
130
  "receiverAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
116
131
  "receiverMemo": "rozo-901",
117
- "amount": "5.021000",
132
+ "amount": "1054.410000",
118
133
  "payTo": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"
119
134
  }
120
135
  }
121
136
  ```
122
137
 
123
- Para Lightning, `deposit.lnInvoice` contiene la cadena BOLT11 que hay que
124
- escanear, y `deposit.amount` está en satoshis.
138
+ Enviar exactamente los campos que entrega este bloque. Para Lightning,
139
+ `deposit.lnInvoice` contiene la cadena BOLT11 que hay que escanear, y
140
+ `deposit.amount` está en satoshis.
125
141
 
126
142
  ## 4. Pagar
127
143
 
128
- Elegir uno. **Modo A** — pagar desde la propia billetera: enviar exactamente
129
- `deposit.amount` de `deposit.tokenSymbol` a `deposit.receiverAddress`, en
130
- `deposit.chain`, incluyendo `deposit.receiverMemo` si lo hay. Copiar la
131
- dirección del JSON; nunca teclearla de nuevo.
144
+ ### La forma sencilla: desde la propia billetera
145
+
146
+ **Sin clave privada, sin variables de entorno, sin configuración.** Abrir
147
+ cualquier billetera y enviar exactamente lo que indica el bloque `deposit` de
148
+ arriba:
149
+
150
+ - el `amount` del `tokenSymbol`,
151
+ - en la `chain`,
152
+ - a la `receiverAddress`, copiada del JSON, nunca tecleada de nuevo.
153
+
154
+ Si el bloque contiene algún otro campo, como `receiverMemo`, incluirlo tal cual;
155
+ forma parte del destino en esa cadena. Para Lightning, escanear o pegar
156
+ `deposit.lnInvoice` en su lugar.
157
+
158
+ Eso es todo el Modo A. Continuar en el paso 5.
159
+
160
+ ### La forma opcional: dejar que el script pague (Modo B)
132
161
 
133
- **Modo B** — dejar que el script pague desde una billetera caliente (solo EVM y Solana):
162
+ Solo si se quiere que esta máquina firme por uno, y solo en cadenas EVM y Solana.
163
+ Esta es la única parte que necesita una clave privada:
134
164
 
135
165
  ```bash
136
166
  # Previsualizar exactamente lo que se firmaría — no firma nada
@@ -143,7 +173,8 @@ ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
143
173
  ```
144
174
 
145
175
  Usar `send-evm.js` con `ROZO_CHECKOUT_EVM_KEY` para Ethereum, BNB Chain,
146
- Polygon y Base. Topes: $100 por transacción, $200 por sesión.
176
+ Polygon y Base. Un solo pago no puede superar los **$1,100**; por encima de eso,
177
+ pagar desde la propia billetera como se explica arriba.
147
178
 
148
179
  ```json
149
180
  {
@@ -188,5 +219,5 @@ el `linkId`, el `rozoPaymentId` y todos los hashes de transacción, y pedir a un
188
219
  persona que lo concilie. No hay garantía de que un segundo pago a una dirección
189
220
  de depósito de un solo uso sea acreditado.
190
221
 
191
- La tabla completa de errores está en [README.md](README.md), y las instrucciones
192
- dirigidas al agente están en [SKILL.md](SKILL.md).
222
+ La tabla completa de errores está en [README.md](../README.md), y las instrucciones
223
+ dirigidas al agente están en [SKILL.md](../SKILL.md).