@rozoai/checkout 0.1.0 → 0.1.2

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/QUICKSTART.zh.md DELETED
@@ -1,178 +0,0 @@
1
- # 快速开始
2
-
3
- [English](QUICKSTART.md) | **简体中文** | [日本語](QUICKSTART.ja.md) | [Español](QUICKSTART.es.md)
4
-
5
- 用 Solana、BNB Chain、Ethereum、Polygon、Base 或 Stellar 上的 USDT/USDC,或者用走
6
- Lightning 的 BTC,去支付一个 OpenRouter Coinbase 收款链接 (Payment Link)。五分钟搞定。
7
- 工作原理与设计理由见 [README.md](README.md)。
8
-
9
- ## 一行命令搞定
10
-
11
- ```bash
12
- npx @rozoai/checkout pay https://payments.coinbase.com/payment-links/pl_01YOURLINKID --with usdt-solana
13
- ```
14
-
15
- 这一条命令会替你跑完下面的每一步:报价、创建订单、核对、确认、充值指令,然后一直轮询到结清。`--with` 可选的币种有:`usdt-solana`、`usdc-solana`、`usdt-bnb`、`usdc-bnb`、`usdt-ethereum`、`usdc-ethereum`、`usdt-polygon`、`usdc-polygon`、`usdc-base`、`usdc-stellar`、`btc-lightning`。
16
-
17
- 加 `--send` 就用热钱包付款而不是用你自己的钱包,加 `--json` 输出机器可读格式。
18
-
19
- 本页剩下的内容就是同一套流程,只不过一步一步来 —— 如果出了问题,或者你想自己写脚本,那才需要看它们。
20
-
21
- ## 开始之前
22
-
23
- - **Node 18 或更高版本**(`node -v`)。别的什么都不用装 —— `npx` 会去拉取 CLI,而克隆下来的
24
- `scripts/dist/*.js` 都是自包含的打包产物。
25
- - **一个钱包**,在你选的链上持有你想用来付款的币种。
26
- - **那个 Coinbase 链接**,例如
27
- `https://payments.coinbase.com/payment-links/pl_01YOURLINKID`。
28
- - 不需要账号,也不需要 API key。这里用到的每个端点都是公开的。
29
-
30
- 先设一次:
31
-
32
- ```bash
33
- LINK="https://payments.coinbase.com/payment-links/pl_01YOURLINKID"
34
- ```
35
-
36
- 链 id:`1` Ethereum · `56` BNB Chain · `137` Polygon · `8453` Base ·
37
- `900` Solana · `1500` Stellar · `lightning` Bitcoin Lightning。
38
-
39
- ## 1. 报价(只读,免费)
40
-
41
- ```bash
42
- node scripts/dist/quote.js --url "$LINK"
43
- ```
44
-
45
- ```json
46
- {
47
- "success": true,
48
- "merchant": "OpenRouter, Inc.",
49
- "invoice": { "amount": "5.00", "fiat": { "amount": "5.00", "currency": "USD" } },
50
- "callerPays": "5.00",
51
- "coinbaseExpiryIso": "2026-08-09T10:00:00.000Z"
52
- }
53
- ```
54
-
55
- `"success": false` 且带 `LINK_NO_LONGER_PAYABLE`,说明这个链接已被付过或已过期 ——
56
- 去要一个新的,然后停止。
57
-
58
- ## 2. 创建订单
59
-
60
- ```bash
61
- node scripts/dist/create-order.js --url "$LINK" --chain 900 --token USDT
62
- ```
63
-
64
- 这一步不动任何资金,未付款的订单会自然过期。完整充值地址 (deposit address) 在此阶段
65
- 会被**扣留** —— 你只拿到打码后的摘要,先用它核对。
66
-
67
- ```json
68
- {
69
- "success": true,
70
- "rozoPaymentId": "11111111-2222-4333-8444-555555555555",
71
- "invoice": { "amount": "5.000000", "currency": "USD" },
72
- "deposit": null,
73
- "depositWithheld": true,
74
- "display": {
75
- "chain": "Solana",
76
- "amount": "5.021000 USDT",
77
- "payToMasked": "9WzDXw...AWWM",
78
- "memoRequirement": "This deposit REQUIRES the memo/tag below. ..."
79
- },
80
- "expiry": { "effectiveDeadlineIso": "2026-08-08T11:00:00.000Z", "minutesOfSlack": 55 }
81
- }
82
- ```
83
-
84
- **继续之前务必核对 `display.amount`。** 它通常大于账单金额 —— 因为它包含了跨桥费用和
85
- 网络费用。记下 `rozoPaymentId`;后面每一条命令都要用它。
86
-
87
- ## 3. 确认
88
-
89
- 只有在你已经决定付款之后,才带上 `--confirm` 重新执行同一条命令:
90
-
91
- ```bash
92
- node scripts/dist/create-order.js --url "$LINK" --chain 900 --token USDT --confirm
93
- ```
94
-
95
- 这会释放完整的充值详情,并记录下发送脚本所需的那条确认。
96
-
97
- ```json
98
- {
99
- "success": true,
100
- "confirmed": true,
101
- "deposit": {
102
- "chain": "Solana",
103
- "tokenSymbol": "USDT",
104
- "receiverAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
105
- "receiverMemo": "rozo-901",
106
- "amount": "5.021000",
107
- "payTo": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"
108
- }
109
- }
110
- ```
111
-
112
- 对于 Lightning,`deposit.lnInvoice` 里是供扫码的 BOLT11 字符串,`deposit.amount`
113
- 的单位是聪 (satoshis)。
114
-
115
- ## 4. 付款
116
-
117
- 二选一。**模式 A** —— 用你自己的钱包付:在 `deposit.chain` 上,把恰好
118
- `deposit.amount` 数量的 `deposit.tokenSymbol` 发送到 `deposit.receiverAddress`,
119
- 如果有 `deposit.receiverMemo` 就带上它。地址直接从 JSON 里复制;绝不要手打重输。
120
-
121
- **模式 B** —— 让脚本从热钱包付款(仅限 EVM 与 Solana):
122
-
123
- ```bash
124
- # 预览将要签名的确切内容 —— 不会签任何名
125
- ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
126
- node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --dry-run
127
-
128
- # 真正发送。--send 是必需的。
129
- ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
130
- node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --send
131
- ```
132
-
133
- Ethereum、BNB Chain、Polygon 和 Base 用 `send-evm.js` 配合 `ROZO_CHECKOUT_EVM_KEY`。
134
- 额度上限:单笔 $100,单会话 $200。
135
-
136
- ```json
137
- {
138
- "success": true,
139
- "submitted": true,
140
- "confirmed": true,
141
- "txHash": "3Bxs4h24hBjHziQ8UJqSjqjbjWQq2sQ3yV9Fq4HrVh5c"
142
- }
143
- ```
144
-
145
- ## 5. 观察结清
146
-
147
- ```bash
148
- node scripts/dist/status.js --rozo-payment-id <rozoPaymentId> --watch --timeout 600
149
- ```
150
-
151
- ```json
152
- {
153
- "success": true,
154
- "state": "settled",
155
- "terminal": true,
156
- "payin": { "txHash": "3Bxs4h24...", "confirmedAt": "2026-08-08T10:05:00.000Z" }
157
- }
158
- ```
159
-
160
- 状态流转依次为 `awaiting_deposit` → `payin_detected` → `payin_confirmed` →
161
- `bridging` → `paying_coinbase` → `settled`。你的链上交易被确认**并不**代表结束:
162
- 要一直轮询到 `settled` 为止。
163
-
164
- ## 出问题时
165
-
166
- 读 `error.code`。最可能遇到的三个:
167
-
168
- | `error.code` | 发生了什么 | 该怎么办 |
169
- |---|---|---|
170
- | `LINK_NO_LONGER_PAYABLE` | 这个链接已经被别人付过,或者已过期 | 找商家要一个新链接;不要付任何钱 |
171
- | `EXPIRY_MARGIN` | 剩余时间太短,不足以安全完成充值、跨桥和结清 | 让订单过期,然后从第 1 步重新开始 |
172
- | `ALREADY_SENT` | 这个订单已经记录过一次发送 | **不要**再发一次;先跑 `status.js` 并去链上核对 |
173
-
174
- **只要已经有钱离开了你的钱包,就绝不要再付一次。** 保留好 `linkId`、
175
- `rozoPaymentId` 和每一个交易 hash,找人来做对账。向一个一次性充值地址付第二笔款,
176
- 并不保证会被入账。
177
-
178
- 完整的错误码表在 [README.md](README.md),面向 agent 的指令在 [SKILL.md](SKILL.md)。
package/README.es.md DELETED
@@ -1,287 +0,0 @@
1
- # rozo-checkout
2
-
3
- [English](README.md) | [简体中文](README.zh.md) | [日本語](README.ja.md) | **Español**
4
-
5
- **[Inicio rápido →](QUICKSTART.es.md)** — pagar un enlace en cinco minutos, sin leer todo esto.
6
-
7
- ```bash
8
- npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
9
- ```
10
-
11
- Pagar un **enlace de pago de Coinbase (Coinbase Payment Link) de OpenRouter** con
12
- una moneda que ese enlace no puede aceptar directamente: BTC por Lightning, o
13
- USDT/USDC en Solana, BNB Chain, Ethereum, Polygon, Base o Stellar.
14
-
15
- Un enlace de pago de Coinbase solo acepta USDC en Base. Este repositorio es una
16
- habilidad de agente (agent skill) —más los scripts de Node que la respaldan— que
17
- enruta cualquiera de las monedas anteriores a través de un puente (bridge): se
18
- obtiene una dirección de depósito (deposit address) de un solo uso para la moneda
19
- que realmente se posee y, una vez que el depósito llega, una billetera fondeadora
20
- (funder wallet) liquida la factura de Coinbase en nombre del usuario.
21
-
22
- En la factura en sí **no hay descuento**: `callerPays` es igual al importe de la
23
- factura. El **depósito** que se envía es una cifra distinta y normalmente es
24
- mayor: incluye las comisiones del puente y de la cadena de origen necesarias para
25
- entregar el importe de la factura en USDC sobre Base. Enviar siempre exactamente
26
- el `deposit.amount` que devuelve el backend; nunca suponer que es igual a la
27
- factura.
28
-
29
- - `SKILL.md` — las instrucciones dirigidas al agente (formato de skill de Claude Code).
30
- - `llms.txt` — un resumen compacto para agentes que leen un solo archivo.
31
- - `scripts/` — la implementación en Node; `src/` es el código fuente y `dist/`
32
- contiene paquetes autocontenidos que se pueden ejecutar con `node` a secas.
33
- - `test/` — pruebas unitarias offline de la lógica de manejo de dinero y de seguridad.
34
- - `PLAN.md` — el documento de diseño que sigue la implementación.
35
-
36
- **No** hace falta una cuenta, una clave de API ni ninguna relación con el
37
- operador para usar esto. Todos los endpoints que invoca son públicos y sin clave.
38
-
39
- ## Cómo funciona
40
-
41
- ```mermaid
42
- flowchart TD
43
- A["Coinbase Payment Link<br/>payments.coinbase.com/payment-links/pl_*"] --> B
44
- B["quote-invoice<br/>(public POST)"] --> C["create-invoice<br/>(public POST)"]
45
- C --> D["Bridge order<br/>one-time deposit address<br/>+ exact amount + expiry"]
46
- D --> E["You send USDT/USDC/BTC<br/>on your chosen chain"]
47
- E --> F["Bridge converts the pay-in"]
48
- F --> G["Funder wallet settles<br/>the Coinbase invoice"]
49
- G --> H["Merchant is paid<br/>(e.g. OpenRouter credit)"]
50
- ```
51
-
52
- Lo mismo en ASCII, para terminales sin mermaid:
53
-
54
- ```
55
- Coinbase Payment Link (pl_* / paymentSession_*)
56
- |
57
- v
58
- [ quote-invoice ] -> merchant, amount, expiry, short-lived quote receipt
59
- |
60
- v
61
- [ create-invoice ] -> bridge order: rozoPaymentId + deposit address
62
- | + exact amount + order expiry
63
- v
64
- you send USDT / USDC / BTC on your chain ------> deposit address
65
- |
66
- v
67
- bridge converts the pay-in ------> funder wallet pays the Coinbase invoice
68
- |
69
- v
70
- merchant credited; poll until the state is `settled`
71
- ```
72
-
73
- Aparecen tres identificadores a lo largo del documento y nunca son intercambiables:
74
-
75
- | Identificador | Qué es |
76
- |---|---|
77
- | `linkId` | el id de Coinbase: `pl_*` (enlace de pago) o `paymentSession_*` (sesión v3) |
78
- | `rozoPaymentId` | el UUID de la orden del puente: se usa para el detalle del depósito y el estado |
79
- | `paymentLink` | una URL de página de pago alojada para la orden del puente (alternativa para humanos) |
80
-
81
- ## Orígenes admitidos
82
-
83
- | Cadena | Id de cadena | Tokens | Notas |
84
- |---|---|---|---|
85
- | Ethereum | `1` | USDC, USDT | 6 decimales |
86
- | BNB Chain | `56` | USDC, USDT | **18 decimales**: la causa habitual de errores por un factor de 10^12 |
87
- | Polygon | `137` | USDC, USDT | 6 decimales |
88
- | Base | `8453` | USDC | 6 decimales |
89
- | Solana | `900` | USDC, USDT | 6 decimales; SPL, puede requerir un memo. SOL nativo **no** está admitido |
90
- | Stellar | `1500` | USDC | 7 decimales; requiere el memo |
91
- | Bitcoin Lightning | `lightning` | BTC | los importes son **satoshis** enteros, pagados mediante una factura BOLT11 (BOLT11) |
92
-
93
- Las monedas de gas nativas (SOL, BNB, ETH, MATIC) y el BTC on-chain no se aceptan.
94
-
95
- ## Inicio rápido
96
-
97
- ### 1. Probar los endpoints públicos con curl
98
-
99
- Reemplazar `pl_01YOURLINKID` por un enlace de pago de Coinbase real. No se
100
- necesita ninguna cabecera de autenticación en nada de lo que sigue.
101
-
102
- ```bash
103
- MPP="https://apiserver.mpprouter.dev/v1/services/rozo-agent-api"
104
- INTENTS="https://intentapiv4.rozo.ai/functions/v1/payment-api"
105
- LINK="https://payments.coinbase.com/payment-links/pl_01YOURLINKID"
106
-
107
- # Cotizarlo: comercio, importe, expiración y un quoteReceipt de ~60 segundos.
108
- curl -s -X POST "$MPP/quote-invoice" \
109
- -H 'content-type: application/json' \
110
- -d "{\"url\":\"$LINK\"}"
111
-
112
- # Crear una orden de puente para, por ejemplo, USDT en Solana.
113
- # Esto crea una orden pero no mueve dinero; una orden sin fondear simplemente expira.
114
- curl -s -X POST "$MPP/create-invoice" \
115
- -H 'content-type: application/json' \
116
- -d "{\"url\":\"$LINK\",\"source\":{\"chainId\":\"900\",\"tokenSymbol\":\"USDT\"}}"
117
-
118
- # Instrucciones de depósito (autoritativas), usando el rozoPaymentId de arriba.
119
- curl -s "$INTENTS/payments/<rozoPaymentId>"
120
-
121
- # Estado del cumplimiento, usando el linkId de Coinbase.
122
- curl -s "$MPP/invoice-status?payment_id=pl_01YOURLINKID"
123
- ```
124
-
125
- `create-invoice` tiene límite de tasa por IP (unas 30/hora); los endpoints de
126
- lectura no.
127
-
128
- ### 2. Usar la CLI
129
-
130
- No hay nada que instalar: `npx` la descarga y la ejecuta:
131
-
132
- ```bash
133
- npx @rozoai/checkout quote <coinbase-link>
134
- npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
135
- npx @rozoai/checkout status <rozoPaymentId>
136
- ```
137
-
138
- `pay` recorre todo el flujo: cotizar, crear la orden, mostrar una revisión
139
- enmascarada, pedir un sí, y luego imprimir las instrucciones de depósito y
140
- consultar hasta la liquidación. Añadir `--send` para pagar desde una billetera
141
- caliente en lugar de la propia, `--json` para salida de máquina y `--help` para
142
- todo lo demás.
143
-
144
- ### 3. O ejecutar los scripts directamente
145
-
146
- Clonar el repositorio da los mismos flujos como scripts individuales: es lo que
147
- usa la habilidad de agente, y lo que la CLI invoca por debajo.
148
-
149
- Cada script imprime exactamente un objeto JSON en stdout. Código de salida `0`
150
- éxito, `1` rechazado/fallido (leer `error.code`), `2` uso incorrecto, `3` enviado
151
- pero sin confirmar.
152
-
153
- ```bash
154
- # Paso 1 — cotización de solo lectura, no cuesta nada
155
- node scripts/dist/quote.js --url "$LINK"
156
-
157
- # Paso 2 — crear la orden (no se mueve dinero; las órdenes sin fondear expiran).
158
- # La dirección de depósito completa se RETIENE en esta etapa: se obtiene
159
- # el resumen enmascarado para revisar, y `depositWithheld: true`.
160
- node scripts/dist/create-order.js --url "$LINK" --chain 900 --token USDT
161
-
162
- # Paso 3 — revisar el importe, la cadena, la dirección enmascarada, el requisito
163
- # de memo y la expiración. Solo cuando se haya decidido pagar, volver a
164
- # ejecutar el mismo comando con --confirm. Esto libera el bloque de
165
- # depósito completo y registra la confirmación que exigen los scripts de envío.
166
- node scripts/dist/create-order.js --url "$LINK" --chain 900 --token USDT --confirm
167
-
168
- # Paso 4a — Modo A: pagar el bloque de depósito desde la propia billetera,
169
- # y luego observar la liquidación
170
- node scripts/dist/status.js --rozo-payment-id <uuid> --watch --timeout 600
171
-
172
- # Paso 4b — Modo B: dejar que el script pague desde una billetera caliente.
173
- # --dry-run no firma nada; un envío real requiere además --send.
174
- ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
175
- node scripts/dist/send-sol.js --rozo-payment-id <uuid> --dry-run
176
- ```
177
-
178
- Los `scripts/dist/*.js` son paquetes autocontenidos: no hace falta `npm install`
179
- en el lugar de la llamada. La CLI anterior es el mismo código con una superficie
180
- más amable: importa estos flujos en lugar de reimplementarlos, así que todas las
181
- comprobaciones de abajo aplican igual sea cual sea el punto de entrada que se
182
- use.
183
-
184
- ## Compilación y pruebas
185
-
186
- ```bash
187
- npm install # solo hace falta para recompilar o para ejecutar las pruebas
188
- npm run build # esbuild -> scripts/dist/*.js (objetivo node18) + blacklist.json
189
- npm test # node:test, totalmente offline
190
- npm run check # build + test
191
- ```
192
-
193
- Las pruebas **no hacen llamadas de red**; cada respuesta del backend es un
194
- fixture en `test/fixtures/`. Cubren la conversión a importes atómicos (6/18
195
- decimales y satoshis de Lightning), la aritmética del margen de expiración, la
196
- normalización de direcciones comprometidas y el comportamiento de fallo cerrado
197
- (fail-closed), la decisión de reutilización de órdenes, el comparador de
198
- verificación posterior a la creación y las reglas de completitud del depósito.
199
-
200
- Dos grupos lanzan procesos hijos reales en lugar de llamar a funciones, porque
201
- prueban cosas que una prueba de un solo proceso no puede: la suite de
202
- concurrencia hace competir a varios procesos por reclamar una misma orden
203
- (exactamente uno puede ganar) y por agotar el tope de la sesión, y la suite de
204
- puntos de entrada ejecuta los scripts de envío compilados para demostrar que
205
- rechazan sin `--send`, sin una confirmación y después de una reclamación previa.
206
-
207
- ## Diseño de seguridad
208
-
209
- Lo más interesante de este repositorio es aquello que se niega a hacer.
210
-
211
- - **Confirmación en dos fases, obligatoria.** `create-order.js` retiene la
212
- dirección de depósito completa, el memo y la factura BOLT11 hasta que se
213
- vuelve a ejecutar con `--confirm`, lo cual registra una confirmación ligada a
214
- un sha256 de esas instrucciones exactas. Los scripts de envío rechazan la
215
- operación si no están presentes tanto `--send` como una confirmación cuyo
216
- digest siga coincidiendo con los datos en vivo, de modo que ni una invocación
217
- accidental ni una dirección de depósito sustituida pueden mover fondos.
218
- - **Factura completa, siempre.** `callerPays` debe ser igual al importe de la
219
- factura y `discount` debe ser `"0"`; cualquier otra cosa aborta con
220
- `NO_DISCOUNT_VIOLATION`. Los campos críticos para la seguridad (`linkId`,
221
- `merchant`, `original`, `callerPays`, el origen reflejado) deben estar
222
- presentes además de ser iguales: un campo ausente es una desviación (drift).
223
- - **Protección contra reutilización.** Crear una orden para un enlace que ya
224
- tiene una orden no expirada devuelve esa orden existente, incluso si ya ha
225
- sido fondeada. Por eso, en cada ejecución se exige que la orden en vivo esté
226
- sin pagar (`payment_unpaid`, sin hash de transacción, sin importe recibido,
227
- sin confirmación) y que coincida con la cadena y el token elegidos por quien
228
- llama. En caso contrario: `ORDER_ALREADY_FUNDED` o `REUSED_SOURCE_MISMATCH`.
229
- - **Regla de dinero detectado, con fallo cerrado.** Una vez que existe cualquier
230
- ingreso, la herramienta nunca informa de un simple fallo, nunca aconseja pagar
231
- de nuevo y nunca reintenta con una orden nueva. Un `amountReceived` que no es
232
- nulo pero resulta ilegible cuenta como dinero, no como ausencia de dinero. Un
233
- backend ilegible se reporta como `unknown`, nunca como `awaiting_deposit`.
234
- - **Instrucciones de depósito completas.** Un importe cero, negativo o no
235
- interpretable aborta la operación. Lightning requiere la BOLT11 (que llega en
236
- `source.lnInvoice` con una dirección vacía). Stellar requiere su memo: un memo
237
- ausente es un aborto duro, nunca se representa como "no se requiere memo".
238
- - **Márgenes de expiración.** El pago se rechaza salvo que la más temprana entre
239
- la expiración de la orden y la de Coinbase esté a más de un margen por cadena
240
- (10 min en EVM y Stellar, 5 min en Solana). Lightning exige además al menos 10
241
- minutos de validez de la BOLT11. Una fecha límite ausente o no interpretable
242
- aborta la operación.
243
- - **Revalidación de la pagabilidad.** Un recibo de cotización hace que la
244
- creación de la orden omita la comprobación en vivo contra Coinbase, y el
245
- enlace puede ser consumido por otra persona en cualquier momento; por eso la
246
- pagabilidad se vuelve a comprobar inmediatamente antes de mostrar la dirección
247
- de depósito, y otra vez como último paso antes de la difusión (broadcast),
248
- después de toda la preparación de RPC. Un estado incompleto de Coinbase se
249
- trata como "no se puede demostrar que sea pagable", no como pagable.
250
- - **Lista de direcciones comprometidas, con fallo cerrado.**
251
- `scripts/src/lib/blacklist.json` incluye una lista incorporada con una
252
- cabecera de procedencia y un sha256 sobre las direcciones. El digest solo
253
- demuestra que esta copia incorporada no ha sido editada desde su fecha de
254
- sincronización; no es una firma de la fuente original. Se comprueban tanto la
255
- dirección de depósito como la billetera emisora. Si el archivo falta, está mal
256
- formado, está vacío o su digest no coincide, se rechaza todo envío en lugar de
257
- continuar sin comprobación.
258
- - **Envío único, entre procesos.** El estado de la orden vive en
259
- `$HOME/.rozo-checkout/state/<uuid>.json`, escrito de forma atómica (archivo
260
- temporal, fsync, renombrado). Cada ciclo de lectura-modificación-escritura de
261
- un archivo de estado —la reclamación, los topes de gasto, el registro de la
262
- orden y la confirmación— se ejecuta dentro de un único archivo de bloqueo
263
- exclusivo, de modo que dos invocaciones concurrentes no pueden ni decidir
264
- ambas que son la primera ni sobrescribir el registro de envío de la otra. Un
265
- envío se reclama *antes* de difundirse, así que un error ambiguo de RPC nunca
266
- puede convertirse en una segunda transferencia. Las transacciones se firman
267
- antes de la difusión para que el hash se conozca de antemano; ante un
268
- resultado ambiguo, los scripts consultan esa transacción exacta en lugar de
269
- volver a difundirla.
270
- - **Controles de la billetera caliente.** Las claves provienen únicamente del
271
- entorno (`ROZO_CHECKOUT_EVM_KEY`, `ROZO_CHECKOUT_SOL_KEY`), nunca se imprimen
272
- y nunca se aceptan por línea de comandos; los errores de bibliotecas y de RPC
273
- se redactan antes de mostrarse, incluidas las URL de proveedor que llevan
274
- credenciales, los tokens bearer y las cadenas con forma de clave. Los scripts
275
- se niegan a ejecutarse cuando cualquier `.env`/`.env.*` del directorio de
276
- trabajo está bajo seguimiento de git, y se niegan con igual firmeza cuando git
277
- no puede demostrar que no lo está. El id de cadena del RPC (o el hash génesis
278
- de Solana) y los decimales on-chain del token se verifican antes de firmar.
279
- Topes: $100 por transacción, $200 acumulados por sesión.
280
- - **Enmascaramiento de direcciones.** El texto muestra `first6...last4`. La
281
- dirección de depósito completa, el memo y la cadena BOLT11 aparecen solo
282
- dentro del objeto `deposit` legible por máquina, de modo que siguen siendo
283
- copiables sin quedar dispersos por los registros.
284
-
285
- ## Licencia
286
-
287
- MIT.