@rozoai/checkout 0.1.1 → 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/README.md CHANGED
@@ -37,13 +37,103 @@ npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
37
37
 
38
38
  Native gas coins (SOL, BNB, ETH, MATIC) and on-chain BTC are not accepted.
39
39
 
40
+ ## Which wallet do I need?
41
+
42
+ **One wallet, on one chain — not one per chain.** Pick whichever coin above you
43
+ already hold and pay from wherever it already lives.
44
+
45
+ - **Any wallet works, and so does an exchange withdrawal.** The default path
46
+ just prints a deposit block: send exactly that `amount` of that
47
+ `tokenSymbol`, on that `chain`, to that `receiverAddress`. Nothing connects to
48
+ a site and nothing is approved in a browser. In practice people use MetaMask
49
+ or Rabby on the EVM chains, Phantom or Solflare on Solana, and a Lightning
50
+ wallet such as Phoenix or Wallet of Satoshi for BTC.
51
+ - **Stellar is the one to be careful with.** Its deposits route through a shared
52
+ address plus `receiverMemo`, so whatever you send from — exchange or wallet —
53
+ must let you set a memo. Omit it and the payment is lost.
54
+ - **Lightning pays an invoice, not an address.** Scan or paste
55
+ `deposit.lnInvoice`; there is no address to send to.
56
+ - **Only `--send` needs a private key**, read from `ROZO_CHECKOUT_EVM_KEY` or
57
+ `ROZO_CHECKOUT_SOL_KEY`, and it covers EVM chains and Solana only. Everything
58
+ else is keyless.
59
+
40
60
  ## Use it from your agent
41
61
 
42
62
  The payload is the same everywhere: the one-liner above, or point the agent at
43
63
  [llms.txt](llms.txt). Agents and scripts should always pass `--with` — the
44
64
  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`.
65
+ the optional `--send` flag signs locally: on Solana it uses the
66
+ `~/.config/solana/id.json` that `solana-keygen` already created, and on EVM an
67
+ encrypted JSON keystore whose passphrase is prompted. A raw key in the
68
+ environment (or a gitignored `.env`) still works for unattended automation.
69
+
70
+ <details>
71
+ <summary><b>Set up a local wallet for <code>--send</code></b> — .env template and per-wallet export steps</summary>
72
+
73
+ **None of this is needed for the default path.** Paying from your own wallet
74
+ needs no key and no configuration, and works with wallets that can never be
75
+ used here — including hardware wallets and exchange accounts.
76
+
77
+ A `.env` in the directory you run from, with every variable this tool reads:
78
+
79
+ ```bash
80
+ # None of this is needed to pay from your own wallet. These are read only
81
+ # when you use --send.
82
+
83
+ # Solana secret key: a base58 string, or a JSON byte array. Only needed if you
84
+ # do NOT have ~/.config/solana/id.json, which is picked up automatically.
85
+ ROZO_CHECKOUT_SOL_KEY=REPLACE_ME_base58_secret_key
86
+
87
+ # EVM raw private key: 64 hex characters, 0x prefix optional. The least safe
88
+ # option — prefer the keystore below.
89
+ ROZO_CHECKOUT_EVM_KEY=0x0000000000000000000000000000000000000000000000000000000000000000
90
+
91
+ # EVM encrypted V3 keystore: path to the file. Preferred over the raw key.
92
+ ROZO_CHECKOUT_EVM_KEYSTORE=/replace/me/keystores/my-hot-wallet
93
+
94
+ # Passphrase for that keystore. Only for unattended runs; on a terminal you
95
+ # are prompted instead, and nothing is stored.
96
+ ROZO_CHECKOUT_KEYSTORE_PASSPHRASE=REPLACE_ME_not_a_real_passphrase
97
+
98
+ # Optional RPC overrides, one per chain id. 8453 = Base, 900 = Solana.
99
+ ROZO_CHECKOUT_RPC_8453=https://mainnet.base.org
100
+ ROZO_CHECKOUT_RPC_900=https://api.mainnet-beta.solana.com
101
+ ```
102
+
103
+ Then lock it down and keep it out of git:
104
+
105
+ ```bash
106
+ chmod 600 .env
107
+ echo '.env' >> .gitignore
108
+ ```
109
+
110
+ **Solana**
111
+
112
+ - `solana-keygen new` writes `~/.config/solana/id.json`. Nothing to configure —
113
+ it is found automatically. This is the path we recommend.
114
+ - **Phantom** → Settings → Export Private Key gives a **base58** string. Put it
115
+ in `ROZO_CHECKOUT_SOL_KEY`.
116
+ - **Solflare** exports a base58 string in current versions and a JSON byte
117
+ array in older ones. Both are accepted as-is.
118
+
119
+ **EVM**
120
+
121
+ - **MetaMask** and **Rabby** → Export private key gives 64 hex characters.
122
+ Paste it into `ROZO_CHECKOUT_EVM_KEY` as-is; the `0x` prefix is optional.
123
+ - **Encrypted keystore (safer).** Browser wallets export raw keys, not
124
+ keystores. To turn one into an encrypted keystore, use Foundry:
125
+ `cast wallet import my-hot-wallet --interactive` prompts for the key and
126
+ writes an encrypted V3 keystore to `~/.foundry/keystores/my-hot-wallet`
127
+ (`--keystore-dir` changes where). Point `ROZO_CHECKOUT_EVM_KEYSTORE` at that
128
+ file. `geth account import` also produces a V3 keystore.
129
+
130
+ **Wallets that cannot be used with `--send`:** hardware wallets (Ledger,
131
+ Trezor), WalletConnect-only mobile wallets, and exchange accounts. None of them
132
+ hand over a signing key, by design. Use the default keyless path instead — it
133
+ works with all of them.
134
+
135
+ </details>
136
+
47
137
 
48
138
  <details>
49
139
  <summary><b>Claude Code</b> — install the skill, or paste the one-liner</summary>
@@ -78,7 +168,8 @@ To pay an OpenRouter / Coinbase payment link, run:
78
168
  npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
79
169
  ```
80
170
 
81
- Wallet: any wallet, no key. `--send` needs the env key.
171
+ Wallet: any wallet, no key. `--send` signs locally using your Solana CLI
172
+ keypair or an encrypted keystore.
82
173
  </details>
83
174
 
84
175
  <details>
@@ -91,7 +182,8 @@ above works unchanged. The shortest path is still the command itself:
91
182
  npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
92
183
  ```
93
184
 
94
- Wallet: any wallet, no key. `--send` needs the env key.
185
+ Wallet: any wallet, no key. `--send` signs locally using your Solana CLI
186
+ keypair or an encrypted keystore.
95
187
  </details>
96
188
 
97
189
  <details>
@@ -104,7 +196,8 @@ To pay an OpenRouter / Coinbase payment link, run:
104
196
  npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
105
197
  ```
106
198
 
107
- Wallet: any wallet, no key. `--send` needs the env key.
199
+ Wallet: any wallet, no key. `--send` signs locally using your Solana CLI
200
+ keypair or an encrypted keystore.
108
201
  </details>
109
202
 
110
203
  <details>
@@ -117,7 +210,8 @@ To pay an OpenRouter / Coinbase payment link, run:
117
210
  npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
118
211
  ```
119
212
 
120
- Wallet: any wallet, no key. `--send` needs the env key.
213
+ Wallet: any wallet, no key. `--send` signs locally using your Solana CLI
214
+ keypair or an encrypted keystore.
121
215
  </details>
122
216
 
123
217
  <details>
@@ -131,7 +225,8 @@ Fetch https://checkout.rozo.ai/llms.txt, then pay this OpenRouter link:
131
225
  npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
132
226
  ```
133
227
 
134
- Wallet: any wallet, no key. `--send` needs the env key.
228
+ Wallet: any wallet, no key. `--send` signs locally using your Solana CLI
229
+ keypair or an encrypted keystore.
135
230
  </details>
136
231
 
137
232
  <details>
@@ -144,7 +239,8 @@ trigger from a script or a chat channel:
144
239
  openclaw agent exec "Pay this OpenRouter link with USDT on Solana by running: npx @rozoai/checkout pay <coinbase-link> --with usdt-solana"
145
240
  ```
146
241
 
147
- Wallet: any wallet, no key. `--send` needs the env key.
242
+ Wallet: any wallet, no key. `--send` signs locally using your Solana CLI
243
+ keypair or an encrypted keystore.
148
244
  </details>
149
245
 
150
246
  <details>
@@ -158,7 +254,8 @@ Pay this OpenRouter link with USDT on Solana by running:
158
254
  npx @rozoai/checkout pay <coinbase-link> --with usdt-solana
159
255
  ```
160
256
 
161
- Wallet: any wallet, no key. `--send` needs the env key.
257
+ Wallet: any wallet, no key. `--send` signs locally using your Solana CLI
258
+ keypair or an encrypted keystore.
162
259
  </details>
163
260
 
164
261
  <details>
@@ -190,7 +287,7 @@ refused/failed (read `error.code`), `2` usage, `3` submitted but unconfirmed.
190
287
  Full walkthrough: [QUICKSTART](docs/QUICKSTART.md).
191
288
 
192
289
  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`.
290
+ `send-sol.js`, which use your Solana CLI keypair or an encrypted keystore.
194
291
  </details>
195
292
 
196
293
  <details>
@@ -206,7 +303,8 @@ to pay this OpenRouter link: <coinbase-link>
206
303
  If the agent has no shell but can make HTTP requests, it can drive the four
207
304
  public endpoints directly — see [how it works](docs/how-it-works.md).
208
305
 
209
- Wallet: any wallet, no key. `--send` needs the env key.
306
+ Wallet: any wallet, no key. `--send` signs locally using your Solana CLI
307
+ keypair or an encrypted keystore.
210
308
  </details>
211
309
 
212
310
  ## Three rules worth knowing
@@ -233,6 +331,12 @@ The full list of what this refuses to do, and why, is in
233
331
 
234
332
  ## Changelog
235
333
 
334
+ - **0.1.2** — Mode B no longer needs a raw private key in an environment
335
+ variable. On Solana it uses the `~/.config/solana/id.json` that
336
+ `solana-keygen` already wrote; on EVM an encrypted V3 keystore whose
337
+ passphrase is prompted. `--keyfile` names either explicitly, and settings can
338
+ come from a gitignored `.env`. Raw env keys still work for unattended
339
+ automation. Key files and `.env` must be `chmod 600` and untracked by git.
236
340
  - **0.1.1** — one spend limit instead of two: a single payment may not exceed
237
341
  $1,100 (sized for a $1,000 credit purchase plus its 5% fee), the cumulative
238
342
  session cap and the `--yes-large` override are removed. Docs make it explicit
@@ -57,6 +57,29 @@ LINK="https://payments.coinbase.com/payment-links/pl_01YOURLINKID"
57
57
  Ids de cadena: `1` Ethereum · `56` BNB Chain · `137` Polygon · `8453` Base ·
58
58
  `900` Solana · `1500` Stellar · `lightning` Bitcoin Lightning.
59
59
 
60
+ ## ¿Qué wallet necesito?
61
+
62
+ **Una wallet, en una cadena: no hace falta una por cada cadena.** Elige la
63
+ moneda que ya tengas y paga desde donde ya esté.
64
+
65
+ Sirve cualquier wallet, y también un retiro desde un exchange: el Mode A de
66
+ abajo solo imprime un bloque de depósito, y envías exactamente ese `amount` de
67
+ ese `tokenSymbol`, en esa `chain`, a esa `receiverAddress`. Nada se conecta a
68
+ ningún sitio ni se aprueba en el navegador. En la práctica la gente usa
69
+ MetaMask o Rabby en las cadenas EVM, Phantom o Solflare en Solana, y una wallet
70
+ Lightning como Phoenix o Wallet of Satoshi para BTC.
71
+
72
+ Dos casos son distintos. **Stellar** se enruta mediante una dirección
73
+ compartida más `receiverMemo`, así que aquello desde lo que envíes debe
74
+ permitirte fijar un memo: si lo omites, el pago se pierde. **Lightning** paga
75
+ la factura BOLT11 de `deposit.lnInvoice`; no hay ninguna dirección a la que
76
+ enviar.
77
+
78
+ Solo `--send` (Mode B) necesita una clave, y cubre únicamente las cadenas EVM y
79
+ Solana: en Solana usa el `~/.config/solana/id.json` que `solana-keygen` ya creó,
80
+ y en EVM un keystore cifrado cuya frase de contraseña se solicita. Una clave en
81
+ bruto en el entorno queda para la automatización desatendida.
82
+
60
83
  ## 1. Cotizarlo (solo lectura, gratis)
61
84
 
62
85
  ```bash
@@ -159,22 +182,114 @@ Eso es todo el Modo A. Continuar en el paso 5.
159
182
 
160
183
  ### La forma opcional: dejar que el script pague (Modo B)
161
184
 
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:
185
+ Solo si se quiere que esta máquina firme, y únicamente en cadenas EVM y Solana.
186
+ Esta es la única parte que necesita una clave.
187
+
188
+ **Solana: usar el par de claves que ya se tiene.** Si alguna vez se ejecutó
189
+ `solana-keygen`, `~/.config/solana/id.json` ya existe y se usa automáticamente:
190
+
191
+ ```bash
192
+ node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --send
193
+ ```
194
+
195
+ **EVM: usar un keystore cifrado.** Exportar un keystore JSON V3 desde la
196
+ billetera y apuntar a él. La frase de contraseña (passphrase) se solicita de
197
+ forma interactiva; nunca se pasa como bandera:
198
+
199
+ ```bash
200
+ ROZO_CHECKOUT_EVM_KEYSTORE=~/wallets/hot.json \
201
+ node scripts/dist/send-evm.js --rozo-payment-id <rozoPaymentId> --send
202
+ ```
203
+
204
+ Cualquiera de los dos archivos se puede indicar explícitamente con
205
+ `--keyfile <path>`, y `--dry-run` funciona con todas las fuentes: deriva la
206
+ dirección y ejecuta todas las comprobaciones sin firmar nada.
207
+
208
+ **Para automatización desatendida**, donde nadie puede escribir una frase de
209
+ contraseña, una clave en bruto en el entorno sigue funcionando igual que antes:
210
+ `ROZO_CHECKOUT_SOL_KEY` o `ROZO_CHECKOUT_EVM_KEY`, o bien
211
+ `ROZO_CHECKOUT_KEYSTORE_PASSPHRASE` junto a un keystore. En una máquina que usa
212
+ una persona, es preferible un archivo de claves.
213
+
214
+ Estos ajustes también pueden vivir en un `.env` en el directorio desde el que se
215
+ ejecuta (o `--env-file <path>`). Solo se leen de él las claves `ROZO_CHECKOUT_*`,
216
+ se analiza como texto plano y nunca se pasa por un shell, y lo que ya esté en el
217
+ entorno real tiene prioridad. **Añadir `.env` al `.gitignore`.**
218
+
219
+ Un archivo de claves o un `.env` no debe ser legible por otros usuarios
220
+ (`chmod 600`) ni estar bajo seguimiento de git. Ambos casos se rechazan, no se advierten.
221
+
222
+ <details>
223
+ <summary><b>Configurar una billetera local para <code>--send</code></b> — plantilla .env y pasos de exportación por billetera</summary>
224
+
225
+ **Nada de esto hace falta para la ruta por defecto.** Pagar desde la propia
226
+ billetera no necesita clave ni configuración, y funciona con billeteras que aquí
227
+ nunca se pueden usar, incluidas las de hardware y las cuentas de exchange.
228
+
229
+ Un `.env` en el directorio desde el que se ejecuta, con todas las variables que
230
+ esta herramienta lee:
164
231
 
165
232
  ```bash
166
- # Previsualizar exactamente lo que se firmaría — no firma nada
167
- ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
168
- node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --dry-run
233
+ # Nada de esto hace falta para pagar desde la propia billetera. Solo se lee
234
+ # cuando se usa --send.
235
+
236
+ # Clave secreta de Solana: una cadena base58 o un arreglo JSON de bytes. Solo
237
+ # hace falta si NO se tiene ~/.config/solana/id.json, que se detecta solo.
238
+ ROZO_CHECKOUT_SOL_KEY=REPLACE_ME_base58_secret_key
239
+
240
+ # Clave privada EVM en bruto: 0x seguido de 64 caracteres hex. La opción menos
241
+ # segura: es preferible el keystore de abajo.
242
+ ROZO_CHECKOUT_EVM_KEY=0x0000000000000000000000000000000000000000000000000000000000000000
169
243
 
170
- # Enviar de verdad. --send es obligatorio.
171
- ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
172
- node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --send
244
+ # Keystore V3 cifrado para EVM: ruta al archivo. Preferible a la clave en bruto.
245
+ ROZO_CHECKOUT_EVM_KEYSTORE=/replace/me/keystores/my-hot-wallet
246
+
247
+ # Frase de contraseña de ese keystore. Solo para ejecuciones desatendidas; en
248
+ # una terminal se solicita y no se guarda nada.
249
+ ROZO_CHECKOUT_KEYSTORE_PASSPHRASE=REPLACE_ME_not_a_real_passphrase
250
+
251
+ # Sobrescrituras de RPC opcionales, una por id de cadena. 8453 = Base,
252
+ # 900 = Solana.
253
+ ROZO_CHECKOUT_RPC_8453=https://mainnet.base.org
254
+ ROZO_CHECKOUT_RPC_900=https://api.mainnet-beta.solana.com
173
255
  ```
174
256
 
175
- Usar `send-evm.js` con `ROZO_CHECKOUT_EVM_KEY` para Ethereum, BNB Chain,
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.
257
+ Después, restringir permisos y mantenerlo fuera de git:
258
+
259
+ ```bash
260
+ chmod 600 .env
261
+ echo '.env' >> .gitignore
262
+ ```
263
+
264
+ **Solana**
265
+
266
+ - `solana-keygen new` escribe `~/.config/solana/id.json`. No hay nada que
267
+ configurar: se encuentra automáticamente. Es la ruta recomendada.
268
+ - **Phantom** → Settings → Export Private Key da una cadena **base58**. Va en
269
+ `ROZO_CHECKOUT_SOL_KEY`.
270
+ - **Solflare** exporta una cadena base58 en las versiones actuales y un arreglo
271
+ JSON de bytes en las antiguas. Ambos se aceptan tal cual.
272
+
273
+ **EVM**
274
+
275
+ - **MetaMask** y **Rabby** exportan la clave privada como 64 caracteres hex.
276
+ Pegarla tal cual en `ROZO_CHECKOUT_EVM_KEY`; el prefijo `0x` es opcional.
277
+ - **Keystore cifrado (más seguro).** Las billeteras de navegador exportan claves
278
+ en bruto, no keystores. Para convertir una en un keystore cifrado, usar
279
+ Foundry: `cast wallet import my-hot-wallet --interactive` pide la clave y
280
+ escribe un keystore V3 cifrado en `~/.foundry/keystores/my-hot-wallet`
281
+ (`--keystore-dir` cambia la ubicación). Apuntar `ROZO_CHECKOUT_EVM_KEYSTORE` a
282
+ ese archivo. `geth account import` también genera un keystore V3.
283
+
284
+ **Billeteras que no se pueden usar con `--send`:** billeteras de hardware
285
+ (Ledger, Trezor), billeteras móviles solo con WalletConnect y cuentas de
286
+ exchange. Por diseño, ninguna entrega una clave de firma. Esos casos usan la
287
+ ruta por defecto sin clave, que funciona con todas ellas.
288
+
289
+ </details>
290
+
291
+ Un solo pago no puede superar **$1,100**; por encima de eso, pagar desde la
292
+ propia billetera como arriba.
178
293
 
179
294
  ```json
180
295
  {
@@ -54,6 +54,16 @@ LINK="https://payments.coinbase.com/payment-links/pl_01YOURLINKID"
54
54
  チェーン id: `1` Ethereum · `56` BNB Chain · `137` Polygon · `8453` Base ·
55
55
  `900` Solana · `1500` Stellar · `lightning` Bitcoin Lightning。
56
56
 
57
+ ## どのウォレットが必要ですか?
58
+
59
+ **ウォレットは 1 つ、チェーンも 1 つで足ります — チェーンごとに用意する必要はありません。**すでに持っている通貨を選び、それが今ある場所から支払ってください。
60
+
61
+ どのウォレットでも構いませんし、取引所からの出金でも構いません。下記の Mode A は入金情報を表示するだけで、示された `amount` の `tokenSymbol` を、その `chain` 上で `receiverAddress` へ送るだけです。どのサイトに接続することも、ブラウザで承認することもありません。実際には、EVM チェーンでは MetaMask や Rabby、Solana では Phantom や Solflare、BTC では Phoenix や Wallet of Satoshi といった Lightning ウォレットがよく使われています。
62
+
63
+ 異なるケースが 2 つあります。**Stellar** は共有アドレスと `receiverMemo` の組み合わせで振り分けられるため、送信元で memo を設定できる必要があります。memo を省くと、その支払いは失われます。**Lightning** は `deposit.lnInvoice` にある BOLT11 インボイスに支払います。送金先アドレスというものはありません。
64
+
65
+ 鍵が必要なのは `--send`(Mode B)だけで、対象は EVM チェーンと Solana のみです。Solana では `solana-keygen` が既に作成した `~/.config/solana/id.json` を、EVM では暗号化された keystore(パスフレーズは対話的に入力)を使います。環境変数の生の鍵は無人自動化向けに残されています。
66
+
57
67
  ## 1. 見積もりを取得する(読み取り専用、無料)
58
68
 
59
69
  ```bash
@@ -153,22 +163,110 @@ satoshi 単位になります。
153
163
 
154
164
  ### 任意の方法: スクリプトに支払わせる(モード B)
155
165
 
156
- このマシンに署名させたい場合にだけ、そして EVM チェーンと Solana でのみ使えます。
157
- 秘密鍵が必要なのはこの部分だけです:
166
+ このマシンに署名させたい場合のみで、対象は EVM チェーンと Solana だけです。鍵が
167
+ 必要なのはこの部分だけです。
168
+
169
+ **Solana — すでにある鍵ペアをそのまま使います。** `solana-keygen` を一度でも実行して
170
+ いれば `~/.config/solana/id.json` が既に存在し、自動的に使われます:
171
+
172
+ ```bash
173
+ node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --send
174
+ ```
175
+
176
+ **EVM — 暗号化された keystore を使います。** ウォレットから V3 形式の JSON keystore を
177
+ 書き出し、それを指定してください。パスフレーズは対話的に尋ねられ、フラグとして渡す
178
+ ことは決してありません:
179
+
180
+ ```bash
181
+ ROZO_CHECKOUT_EVM_KEYSTORE=~/wallets/hot.json \
182
+ node scripts/dist/send-evm.js --rozo-payment-id <rozoPaymentId> --send
183
+ ```
184
+
185
+ どちらのファイルも `--keyfile <path>` で明示的に指定できます。`--dry-run` はすべての
186
+ 取得元で機能し、アドレスを導出してすべてのチェックを実行しますが、署名は行いません。
187
+
188
+ **無人自動化の場合**(パスフレーズを入力できる人がいない場合)は、環境変数の生の鍵が
189
+ これまでどおり使えます — `ROZO_CHECKOUT_SOL_KEY` または `ROZO_CHECKOUT_EVM_KEY`、
190
+ あるいは keystore と併せて `ROZO_CHECKOUT_KEYSTORE_PASSPHRASE` です。人が使うマシンでは
191
+ 鍵ファイルを優先してください。
192
+
193
+ これらの設定は、実行するディレクトリの `.env` に置くこともできます(`--env-file <path>`
194
+ でも指定できます)。読み込まれるのは `ROZO_CHECKOUT_*` のキーだけで、ファイルはテキスト
195
+ として解析され、シェルで評価されることは決してありません。実際の環境変数のほうが優先
196
+ されます。**`.env` は `.gitignore` に追加してください。**
197
+
198
+ 鍵ファイルと `.env` は他のユーザーから読めてはならず(`chmod 600`)、git で追跡されて
199
+ いてもいけません。どちらの場合も警告ではなく拒否されます。
200
+
201
+ <details>
202
+ <summary><b><code>--send</code> 用のローカルウォレット設定</b> — .env テンプレートとウォレット別の書き出し手順</summary>
203
+
204
+ **既定の経路ではここに書かれたものは一切不要です。** 自分のウォレットから支払う場合、
205
+ 鍵も設定も要りません。しかもここでは決して使えないウォレット — ハードウェアウォレットや
206
+ 取引所アカウントを含む — でも支払えます。
207
+
208
+ コマンドを実行するディレクトリに `.env` を置きます。本ツールが読み取る変数の全一覧です:
158
209
 
159
210
  ```bash
160
- # 署名される内容を正確にプレビューします — 署名は一切行いません
161
- ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
162
- node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --dry-run
211
+ # 自分のウォレットから支払う場合、以下はどれも不要です。--send を使うときだけ
212
+ # 読み込まれます。
213
+
214
+ # Solana の秘密鍵: base58 文字列、または JSON のバイト配列。
215
+ # ~/.config/solana/id.json (自動的に使われます) が無い場合にのみ必要です。
216
+ ROZO_CHECKOUT_SOL_KEY=REPLACE_ME_base58_secret_key
217
+
218
+ # EVM の生の秘密鍵: 0x + 16 進 64 文字。最も安全でない選択肢です。
219
+ # 下の keystore を優先してください。
220
+ ROZO_CHECKOUT_EVM_KEY=0x0000000000000000000000000000000000000000000000000000000000000000
163
221
 
164
- # 実際に送金します。--send は必須です。
165
- ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
166
- node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --send
222
+ # EVM の暗号化 V3 keystore: そのファイルへのパス。上の生の鍵より推奨されます。
223
+ ROZO_CHECKOUT_EVM_KEYSTORE=/replace/me/keystores/my-hot-wallet
224
+
225
+ # その keystore のパスフレーズ。無人実行のときだけ必要で、端末では対話的に
226
+ # 尋ねられ、保存もされません。
227
+ ROZO_CHECKOUT_KEYSTORE_PASSPHRASE=REPLACE_ME_not_a_real_passphrase
228
+
229
+ # 任意の RPC 上書き。チェーン id ごとに 1 行。8453 = Base、900 = Solana。
230
+ ROZO_CHECKOUT_RPC_8453=https://mainnet.base.org
231
+ ROZO_CHECKOUT_RPC_900=https://api.mainnet-beta.solana.com
167
232
  ```
168
233
 
169
- Ethereum、BNB Chain、Polygon、Base では `send-evm.js` を `ROZO_CHECKOUT_EVM_KEY` と
170
- 併せて使います。1 回の支払いは **$1,100** を超えられません。それを超える場合は、上記の
171
- とおり自分のウォレットから支払ってください。
234
+ そのうえで権限を絞り、git に入らないようにします:
235
+
236
+ ```bash
237
+ chmod 600 .env
238
+ echo '.env' >> .gitignore
239
+ ```
240
+
241
+ **Solana**
242
+
243
+ - `solana-keygen new` は `~/.config/solana/id.json` を書き出します。設定は不要で、
244
+ 自動的に見つかります。これが推奨の経路です。
245
+ - **Phantom** → Settings → Export Private Key で得られるのは **base58** 文字列です。
246
+ `ROZO_CHECKOUT_SOL_KEY` に設定してください。
247
+ - **Solflare** は現行バージョンでは base58 文字列、古いバージョンでは JSON のバイト配列を
248
+ 書き出します。どちらもそのまま使えます。
249
+
250
+ **EVM**
251
+
252
+ - **MetaMask** と **Rabby** の秘密鍵の書き出しは 16 進 64 文字です。そのまま
253
+ `ROZO_CHECKOUT_EVM_KEY` に貼り付けてください。`0x` 接頭辞は付けても付けなくても
254
+ 構いません。
255
+ - **暗号化 keystore (より安全)。** ブラウザーウォレットが書き出せるのは生の鍵だけで、
256
+ keystore ではありません。生の鍵を暗号化 keystore に変えるには Foundry を使います:
257
+ `cast wallet import my-hot-wallet --interactive` が鍵の入力を促し、暗号化された
258
+ V3 keystore を `~/.foundry/keystores/my-hot-wallet` に書き出します
259
+ (`--keystore-dir` で場所を変更できます)。`ROZO_CHECKOUT_EVM_KEYSTORE` をその
260
+ ファイルに向けてください。`geth account import` も V3 keystore を生成します。
261
+
262
+ **`--send` に使えないウォレット:** ハードウェアウォレット (Ledger、Trezor)、
263
+ WalletConnect 専用のモバイルウォレット、取引所アカウント。いずれも設計上、署名鍵を
264
+ 渡しません。これらの場合は既定の鍵なしの経路を使ってください — すべてで動作します。
265
+
266
+ </details>
267
+
268
+ 1 回の支払いは **$1,100** を超えられません。それ以上は上記のとおり自分のウォレットから
269
+ 支払ってください。
172
270
 
173
271
  ```json
174
272
  {
@@ -54,6 +54,26 @@ LINK="https://payments.coinbase.com/payment-links/pl_01YOURLINKID"
54
54
  Chain ids: `1` Ethereum · `56` BNB Chain · `137` Polygon · `8453` Base ·
55
55
  `900` Solana · `1500` Stellar · `lightning` Bitcoin Lightning.
56
56
 
57
+ ## Which wallet do I need?
58
+
59
+ **One wallet, on one chain — not one per chain.** Pick whichever coin you
60
+ already hold and pay from wherever it already lives.
61
+
62
+ Any wallet works, and so does an exchange withdrawal: Mode A below just prints
63
+ a deposit block, and you send exactly that `amount` of that `tokenSymbol`, on
64
+ that `chain`, to that `receiverAddress`. Nothing connects to a site and nothing
65
+ is approved in a browser. In practice people use MetaMask or Rabby on the EVM
66
+ chains, Phantom or Solflare on Solana, and a Lightning wallet such as Phoenix
67
+ or Wallet of Satoshi for BTC.
68
+
69
+ Two cases differ. **Stellar** routes through a shared address plus
70
+ `receiverMemo`, so whatever you send from must let you set a memo — omit it and
71
+ the payment is lost. **Lightning** pays the BOLT11 invoice in
72
+ `deposit.lnInvoice`; there is no address to send to.
73
+
74
+ Only `--send` (Mode B) needs a private key, from `ROZO_CHECKOUT_EVM_KEY` or
75
+ `ROZO_CHECKOUT_SOL_KEY`, and it covers EVM chains and Solana only.
76
+
57
77
  ## 1. Quote it (read-only, free)
58
78
 
59
79
  ```bash
@@ -155,21 +175,111 @@ That is the whole of Mode A. Skip to step 5.
155
175
  ### The optional way: let the script pay (Mode B)
156
176
 
157
177
  Only if you want this machine to sign for you, and only on EVM chains and
158
- Solana. This is the only part that needs a private key:
178
+ Solana. This is the only part that needs a key.
179
+
180
+ **Solana — use the keypair you already have.** If you have ever run
181
+ `solana-keygen`, `~/.config/solana/id.json` already exists and is used
182
+ automatically:
159
183
 
160
184
  ```bash
161
- # Preview exactly what would be signed — signs nothing
162
- ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
163
- node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --dry-run
185
+ node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --send
186
+ ```
164
187
 
165
- # Actually send. --send is mandatory.
166
- ROZO_CHECKOUT_SOL_KEY=<base58 secret key> \
167
- node scripts/dist/send-sol.js --rozo-payment-id <rozoPaymentId> --send
188
+ **EVM — use an encrypted keystore.** Export a V3 JSON keystore from your
189
+ wallet and point at it. The passphrase is prompted; it is never a flag:
190
+
191
+ ```bash
192
+ ROZO_CHECKOUT_EVM_KEYSTORE=~/wallets/hot.json \
193
+ node scripts/dist/send-evm.js --rozo-payment-id <rozoPaymentId> --send
168
194
  ```
169
195
 
170
- Use `send-evm.js` with `ROZO_CHECKOUT_EVM_KEY` for Ethereum, BNB Chain,
171
- Polygon and Base. A single payment may not exceed **$1,100**; above that, pay
172
- from your own wallet as above.
196
+ Either file can also be given explicitly with `--keyfile <path>`, and
197
+ `--dry-run` works with every source: it derives the address and runs all the
198
+ checks without signing anything.
199
+
200
+ **For unattended automation**, where nobody can type a passphrase, a raw key in
201
+ the environment still works exactly as before — `ROZO_CHECKOUT_SOL_KEY` or
202
+ `ROZO_CHECKOUT_EVM_KEY`, or `ROZO_CHECKOUT_KEYSTORE_PASSPHRASE` alongside a
203
+ keystore. On a machine a person uses, prefer a key file.
204
+
205
+ These settings can also live in a `.env` in the directory you run from (or
206
+ `--env-file <path>`). Only `ROZO_CHECKOUT_*` keys are read from it, it is
207
+ parsed as plain text and never run through a shell, and anything already in
208
+ your real environment wins. **Add `.env` to your `.gitignore`.**
209
+
210
+ A key file or `.env` must not be readable by other users (`chmod 600`) and must
211
+ not be tracked by git. Both are refused rather than warned about.
212
+
213
+ <details>
214
+ <summary><b>Set up a local wallet for <code>--send</code></b> — .env template and per-wallet export steps</summary>
215
+
216
+ **None of this is needed for the default path.** Paying from your own wallet
217
+ needs no key and no configuration, and works with wallets that can never be
218
+ used here — including hardware wallets and exchange accounts.
219
+
220
+ A `.env` in the directory you run from, with every variable this tool reads:
221
+
222
+ ```bash
223
+ # None of this is needed to pay from your own wallet. These are read only
224
+ # when you use --send.
225
+
226
+ # Solana secret key: a base58 string, or a JSON byte array. Only needed if you
227
+ # do NOT have ~/.config/solana/id.json, which is picked up automatically.
228
+ ROZO_CHECKOUT_SOL_KEY=REPLACE_ME_base58_secret_key
229
+
230
+ # EVM raw private key: 64 hex characters, 0x prefix optional. The least safe
231
+ # option — prefer the keystore below.
232
+ ROZO_CHECKOUT_EVM_KEY=0x0000000000000000000000000000000000000000000000000000000000000000
233
+
234
+ # EVM encrypted V3 keystore: path to the file. Preferred over the raw key.
235
+ ROZO_CHECKOUT_EVM_KEYSTORE=/replace/me/keystores/my-hot-wallet
236
+
237
+ # Passphrase for that keystore. Only for unattended runs; on a terminal you
238
+ # are prompted instead, and nothing is stored.
239
+ ROZO_CHECKOUT_KEYSTORE_PASSPHRASE=REPLACE_ME_not_a_real_passphrase
240
+
241
+ # Optional RPC overrides, one per chain id. 8453 = Base, 900 = Solana.
242
+ ROZO_CHECKOUT_RPC_8453=https://mainnet.base.org
243
+ ROZO_CHECKOUT_RPC_900=https://api.mainnet-beta.solana.com
244
+ ```
245
+
246
+ Then lock it down and keep it out of git:
247
+
248
+ ```bash
249
+ chmod 600 .env
250
+ echo '.env' >> .gitignore
251
+ ```
252
+
253
+ **Solana**
254
+
255
+ - `solana-keygen new` writes `~/.config/solana/id.json`. Nothing to configure —
256
+ it is found automatically. This is the path we recommend.
257
+ - **Phantom** → Settings → Export Private Key gives a **base58** string. Put it
258
+ in `ROZO_CHECKOUT_SOL_KEY`.
259
+ - **Solflare** exports a base58 string in current versions and a JSON byte
260
+ array in older ones. Both are accepted as-is.
261
+
262
+ **EVM**
263
+
264
+ - **MetaMask** and **Rabby** → Export private key gives 64 hex characters.
265
+ Paste it into `ROZO_CHECKOUT_EVM_KEY` as-is; the `0x` prefix is optional.
266
+ - **Encrypted keystore (safer).** Browser wallets export raw keys, not
267
+ keystores. To turn one into an encrypted keystore, use Foundry:
268
+ `cast wallet import my-hot-wallet --interactive` prompts for the key and
269
+ writes an encrypted V3 keystore to `~/.foundry/keystores/my-hot-wallet`
270
+ (`--keystore-dir` changes where). Point `ROZO_CHECKOUT_EVM_KEYSTORE` at that
271
+ file. `geth account import` also produces a V3 keystore.
272
+
273
+ **Wallets that cannot be used with `--send`:** hardware wallets (Ledger,
274
+ Trezor), WalletConnect-only mobile wallets, and exchange accounts. None of them
275
+ hand over a signing key, by design. Use the default keyless path instead — it
276
+ works with all of them.
277
+
278
+ </details>
279
+
280
+
281
+ A single payment may not exceed **$1,100**; above that, pay from your own
282
+ wallet as above.
173
283
 
174
284
  ```json
175
285
  {