@rozoai/checkout 0.1.14 → 0.1.15

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
@@ -372,6 +372,104 @@ keypair or an encrypted keystore, and supports EVM chains and Solana only —
372
372
  Stellar and Lightning are Mode A only.
373
373
  </details>
374
374
 
375
+ ## Paying many invoices (batch / resellers)
376
+
377
+ Each OpenRouter top-up is its own Coinbase link, so paying many is a loop: one
378
+ `pay` per link, one logged result per link. Install once
379
+ (`npm i -g @rozoai/checkout`) so each run skips the npx download, run the links
380
+ one at a time, and pay each deposit right after it is created.
381
+
382
+ ```bash
383
+ #!/usr/bin/env bash
384
+ # links.txt: one Coinbase link per line (payment-links/pl_* or payment-sessions/paymentSession_*)
385
+ mkdir -p runs
386
+ while IFS= read -r link; do
387
+ link="${link%$'\r'}"; link="${link%%\?*}"
388
+ [ -n "$link" ] || continue
389
+ id="${link##*/}"
390
+ rozo-checkout pay "$link" --with btc-lightning --yes --json --no-watch \
391
+ --email you@example.com </dev/null > "runs/$id.json"
392
+ code=$?
393
+ row=$(jq -r --arg id "$id" --arg code "$code" '[$id, $code,
394
+ (.order.rozoPaymentId // .error.details.body.rozoPaymentId // "-"),
395
+ (if .success then "pending: pay before " + (.order.expiry.effectiveDeadlineIso // "?")
396
+ else (.error.code // .send.error.code // "FAILED") end)] | @tsv' \
397
+ "runs/$id.json" 2>/dev/null) || row="$id $code - NO_OUTPUT"
398
+ printf '%s\n' "$row" >> runs/batch.tsv
399
+ done < links.txt
400
+ ```
401
+
402
+ - `--yes` is required when stdin is not a terminal, `--json` prints exactly one
403
+ JSON object, and `--no-watch` returns as soon as the deposit details exist.
404
+ Without `--no-watch`, `pay --json` first waits for settlement (up to
405
+ `--timeout`, default 900 s) and prints nothing until then, invoice included.
406
+ - Without `--send` (the loop above), a successful `pay --no-watch` means the
407
+ order and its deposit details exist. **No money has moved yet**, which is
408
+ why the log says `pending`. With `--send`, the CLI may already have
409
+ broadcast your payment, so never pay that deposit by hand as well. A link is
410
+ paid only when `status` later reports `settled`.
411
+ - `order.rozoPaymentId` names the order and `order.deposit` says what to pay.
412
+ Lightning: `deposit.lnInvoice` (the BOLT11) for `deposit.amount` sats. Other
413
+ coins: `deposit.receiverAddress` and `deposit.amount`, plus
414
+ `deposit.receiverMemo` on Stellar. `--send` cannot pay Lightning or Stellar.
415
+ - The deadline to watch is `order.expiry.effectiveDeadlineIso`, not
416
+ `deposit.expiresAt`: it is the earlier of our order expiry and the Coinbase
417
+ link expiry. Stop paying at least `order.expiry.marginMinutes` before it,
418
+ since settlement needs that much time.
419
+ - If time has passed since you created the order, do not pay saved deposit
420
+ details blindly. Re-run the same `pay` command (same `--with`): while the
421
+ order is still payable it re-checks the link and the deadline and hands back
422
+ the same order. Pay only if that succeeds.
423
+
424
+ Check settlement by `rozoPaymentId` (a link alone is only resolved from this
425
+ machine's own records in `~/.rozo-checkout/state`):
426
+
427
+ ```bash
428
+ rozo-checkout status <rozoPaymentId> --json | jq -r '.state, .escalate'
429
+ rozo-checkout status <rozoPaymentId> --watch --timeout 900 --json # poll every 10 s
430
+ ```
431
+
432
+ Exit 0 means the check itself ran cleanly, not that the invoice settled:
433
+ `expired_unfunded` also exits 0. Always read `state`.
434
+
435
+ **Retrying without paying twice.** Running `pay` again on the same link does
436
+ not create a second order while its order is open: you get the same order
437
+ back, and once money has arrived `pay` refuses with `ORDER_ALREADY_ACTIVE` or
438
+ `ORDER_ALREADY_FUNDED`. Only after an order expired with nothing received does
439
+ `pay` on the same link create a new order. The risk is paying a deposit twice, so before acting on
440
+ a link again, run `status` on its `rozoPaymentId`:
441
+
442
+ | `status` result | What to do |
443
+ | --- | --- |
444
+ | `escalate: true` (includes `underpaid`, `stuck_after_payment`; exit 1) | Do not pay again. Contact support with the link, `rozoPaymentId` and any tx hash or payment preimage. |
445
+ | `state: settled` | Done. Skip this link. |
446
+ | `state: awaiting_deposit` | Still open, but a payment you just sent may not be detected yet. First check your wallet: if a send or Lightning payment to this deposit exists or is pending, wait and poll. Only if nothing was sent, re-run the same `pay` to re-check it, then pay the deposit once. |
447
+ | `state: payin_detected`, `payin_confirmed`, `bridging`, `paying_coinbase` | Money is in flight. Wait and poll; do not pay again. |
448
+ | `state: expired_unfunded` | Nothing has arrived and this order is dead. **First check your own wallet**: if you sent anything to the old deposit, or a Lightning payment is still pending, do not pay again; contact support with the link and `rozoPaymentId` (we cannot see a pending Lightning payment). If nothing was sent, re-run the same `pay` on the same link with the same `--with`: it creates a new order. If that answers `PAYMENT_EXPIRED`, see below. |
449
+ | `state: unknown` (exit 1) | The backend could not be read. Not proof that nothing was paid: retry `status`, not `pay`. |
450
+
451
+ - Exit codes: `0` ok, `1` refused or failed (read `error.code`), `2` usage
452
+ error (nothing was created), `3` the watch window ended before a final
453
+ state. Exit 3 means money may still be in flight: keep polling, do not pay
454
+ again.
455
+ - Use the same `--with` coin on every run for a link. A different coin can be
456
+ refused with `REUSED_SOURCE_MISMATCH` or change the open order's deposit.
457
+ - `LINK_USED_OR_EXPIRED` or `LINK_NO_LONGER_PAYABLE`: the Coinbase link itself
458
+ is already paid or expired. Check your OpenRouter balance and get a new link
459
+ if it was not credited.
460
+ - `PAYMENT_EXPIRED`: an earlier order for this link expired. Read
461
+ `error.details.body`: with `retryable: true` (`confirmed: false`) the old
462
+ order cannot be proved unfunded yet, so wait a few minutes and retry the same
463
+ `pay`; with `confirmed: true` the link has used all its re-orders, so get a
464
+ new link from OpenRouter.
465
+ - `RATE_LIMITED`: order creation is capped per IP per hour (currently 30
466
+ requests, and each `pay` makes two), so plan on about 15 links per hour from
467
+ one IP. Wait for the next hour and resume with the links not yet `settled`.
468
+ Need more? Email us.
469
+
470
+ Questions about a batch? Email hi@rozo.ai, or reach us on
471
+ [X](https://x.com/ROZOai) or [Discord](https://discord.gg/EfWejgTbuU).
472
+
375
473
  ## Three rules worth knowing
376
474
 
377
475
  - **The deposit address is one-time.** Never reuse one from an older order, a
@@ -400,6 +498,14 @@ The full list of what this refuses to do, and why, is in
400
498
 
401
499
  ## Changelog
402
500
 
501
+ - **0.1.15**: corrected guidance after an order expires unpaid. First check
502
+ your own wallet that nothing was sent to the old deposit and no Lightning
503
+ payment is pending; if nothing was sent, re-run the same `pay` on the same
504
+ link (the router opens a new order once it has verified the old one is
505
+ unfunded). `PAYMENT_EXPIRED` with `retryable: true` means try again in a few
506
+ minutes; `LINK_USED_OR_EXPIRED` or `PAYMENT_EXPIRED` with `confirmed: true`
507
+ means get a new link from the merchant. New README section on paying many
508
+ invoices (batch / resellers).
403
509
  - **0.1.14**: optional `--email <addr>` on `pay` (and on the create-order
404
510
  scripts) stores a contact email with the order so ROZO can reach you if the
405
511
  payment needs attention. Never required; an invalid address is rejected
@@ -330,7 +330,7 @@ Leer `error.code`. Los tres con los que es más probable toparse:
330
330
  | `error.code` | Qué ocurrió | Qué hacer |
331
331
  |---|---|---|
332
332
  | `LINK_NO_LONGER_PAYABLE` | alguien ya pagó el enlace, o expiró | pedir al comercio un enlace nuevo; no pagar nada |
333
- | `EXPIRY_MARGIN` | queda muy poco tiempo para fondear, puentear y liquidar de forma segura | dejar que la orden expire y volver a empezar desde el paso 1 |
333
+ | `EXPIRY_MARGIN` | queda muy poco tiempo para fondear, puentear y liquidar de forma segura | no fondear esta orden; dejar que expire y volver a empezar desde el paso 1 con el mismo enlace (se crea una orden nueva cuando se comprueba que la anterior no recibió fondos). Si responde `LINK_USED_OR_EXPIRED`, o `PAYMENT_EXPIRED` con `confirmed: true`, pedir al comercio un enlace nuevo |
334
334
  | `ALREADY_SENT` | ya hay un envío registrado para esta orden | **no** enviar de nuevo; ejecutar `status.js` y revisar primero la cadena |
335
335
 
336
336
  **Si algo de dinero ya salió de la billetera, nunca pagar de nuevo.** Conservar
@@ -306,7 +306,7 @@ node scripts/dist/status.js --rozo-payment-id <rozoPaymentId> --watch --timeout
306
306
  | `error.code` | 何が起きたか | どうするか |
307
307
  |---|---|---|
308
308
  | `LINK_NO_LONGER_PAYABLE` | そのリンクは既に誰かが支払ったか、期限切れです | 加盟店に新しいリンクを依頼してください。何も支払わないこと |
309
- | `EXPIRY_MARGIN` | 入金・ブリッジ・決済完了を安全に行うには残り時間が足りません | その注文は期限切れにさせ、ステップ 1 からやり直してください |
309
+ | `EXPIRY_MARGIN` | 入金・ブリッジ・決済完了を安全に行うには残り時間が足りません | この注文には入金しないでください。期限切れになるのを待ち、同じリンクでステップ 1 からやり直してください(旧注文が未入金と確認されると新しい注文が作られます)。`LINK_USED_OR_EXPIRED`、または `confirmed: true` の `PAYMENT_EXPIRED` が返った場合は、加盟店に新しいリンクを依頼してください |
310
310
  | `ALREADY_SENT` | この注文に対する送金が既に記録されています | 再送信しては**いけません**。まず `status.js` を実行し、チェーンを確認してください |
311
311
 
312
312
  **ウォレットから既に資金が出ている場合は、決して二重に支払わないでください。**
@@ -322,7 +322,7 @@ Read `error.code`. The three you are most likely to hit:
322
322
  | `error.code` | What happened | What to do |
323
323
  |---|---|---|
324
324
  | `LINK_NO_LONGER_PAYABLE` | someone already paid the link, or it expired | ask the merchant for a fresh link; do not pay anything |
325
- | `EXPIRY_MARGIN` | too little time left to fund, bridge and settle safely | let the order expire, then start again from step 1 |
325
+ | `EXPIRY_MARGIN` | too little time left to fund, bridge and settle safely | do not fund this order; let it expire, then re-run from step 1 on the same link (a new order is created once the old one is proved unfunded). If that answers `LINK_USED_OR_EXPIRED` or `PAYMENT_EXPIRED` with `confirmed: true`, ask the merchant for a fresh link |
326
326
  | `ALREADY_SENT` | a send is already recorded for this order | do **not** send again; run `status.js` and check the chain first |
327
327
 
328
328
  **If any money has already left your wallet, never pay again.** Keep the
@@ -281,7 +281,7 @@ node scripts/dist/status.js --rozo-payment-id <rozoPaymentId> --watch --timeout
281
281
  | `error.code` | 发生了什么 | 该怎么办 |
282
282
  |---|---|---|
283
283
  | `LINK_NO_LONGER_PAYABLE` | 这个链接已经被别人付过,或者已过期 | 找商家要一个新链接;不要付任何钱 |
284
- | `EXPIRY_MARGIN` | 剩余时间太短,不足以安全完成充值、跨桥和结清 | 让订单过期,然后从第 1 步重新开始 |
284
+ | `EXPIRY_MARGIN` | 剩余时间太短,不足以安全完成充值、跨桥和结清 | 不要给这个订单充值;等它过期后,用同一个链接从第 1 步重新开始(确认旧订单未收到付款后会生成新订单)。如果返回 `LINK_USED_OR_EXPIRED`,或 `PAYMENT_EXPIRED` 且 `confirmed: true`,就找商家要一个新链接 |
285
285
  | `ALREADY_SENT` | 这个订单已经记录过一次发送 | **不要**再发一次;先跑 `status.js` 并去链上核对 |
286
286
 
287
287
  **只要已经有钱离开了你的钱包,就绝不要再付一次。** 保留好 `linkId`、
package/llms.txt CHANGED
@@ -163,6 +163,14 @@ private key (EVM and Solana only); every other path is keyless.
163
163
  - After any on-chain payment is detected, never retry into a new order and never
164
164
  label the payment a normal failure — keep the tx hash and rozoPaymentId, keep
165
165
  polling, and escalate if it stays stuck.
166
+ - An order that expired unfunded does not spend its link. First check your wallet: if
167
+ anything was sent to the old deposit, or a Lightning payment is still pending, do not
168
+ pay again; contact support with linkId + rozoPaymentId (the router cannot see a
169
+ pending Lightning payment). If nothing was sent, create-invoice on the SAME link again:
170
+ the router makes a new order once every earlier order is proved unfunded.
171
+ 409 PAYMENT_EXPIRED retryable:true (confirmed:false) = not verifiable yet, wait a few
172
+ minutes and retry. 409 PAYMENT_EXPIRED confirmed:true or LINK_USED_OR_EXPIRED = ask
173
+ the merchant for a new link. 409 ORDER_ALREADY_ACTIVE = funds seen, do not pay again.
166
174
 
167
175
  ## Errors
168
176
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rozoai/checkout",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "type": "module",
5
5
  "description": "Pay OpenRouter, or any Coinbase invoice, with the crypto you already hold: USDT/USDC on Solana, BNB Chain, Ethereum or Polygon, USDC on Base or Stellar, or BTC over Lightning. No Coinbase account.",
6
6
  "license": "MIT",
@@ -55001,7 +55001,7 @@ function classifyStatus({
55001
55001
  }
55002
55002
  const exp = payment?.expiresAt ? Date.parse(payment.expiresAt) : NaN;
55003
55003
  if (Number.isFinite(exp) && exp < now) {
55004
- return mk("expired_unfunded", "The order expired before any funds arrived. Safe to retry.", {
55004
+ return mk("expired_unfunded", "The order expired before any funds arrived. This order can no longer be paid.", {
55005
55005
  terminal: true
55006
55006
  });
55007
55007
  }
@@ -55027,7 +55027,7 @@ function classifyStatus({
55027
55027
  case "payment_expired":
55028
55028
  return moneyDetected ? mk("stuck_after_payment", "Order expired AFTER funds arrived \u2014 escalate immediately.", {
55029
55029
  escalate: true
55030
- }) : mk("expired_unfunded", "Order expired unfunded. Safe to retry.", { terminal: true });
55030
+ }) : mk("expired_unfunded", "Order expired unfunded. This order can no longer be paid.", { terminal: true });
55031
55031
  case "payment_bounced":
55032
55032
  case "payment_refunded":
55033
55033
  return mk("stuck_after_payment", `Order ended as ${payment.status} \u2014 escalate.`, {
@@ -55977,6 +55977,23 @@ async function snapshot({ rozoPaymentId, linkId, provider: explicitProvider }) {
55977
55977
  errors: [statusError, paymentError].filter(Boolean)
55978
55978
  };
55979
55979
  }
55980
+ var EXPIRED_UNFUNDED_GUIDANCE = "This order expired before any funds arrived. First check your own wallet: if anything was sent to the old deposit address, or a Lightning payment is still pending, do not pay again; contact support with the linkId and rozoPaymentId (the router cannot see a pending Lightning payment). If nothing was sent, re-run the same pay on the same link with the same --with: it creates a new order for this link. If pay answers PAYMENT_EXPIRED with retryable: true, the old order cannot be verified yet; wait a few minutes and retry. If it answers LINK_USED_OR_EXPIRED, or PAYMENT_EXPIRED with confirmed: true, this link cannot be paid any more; get a new payment link from the merchant (OpenRouter). If it answers ORDER_ALREADY_ACTIVE, a payment was found: do not pay again; contact support.";
55981
+ function statusGuidance(result) {
55982
+ if (result.escalate) {
55983
+ return "MONEY DETECTED and the order is not on a healthy path. Do NOT pay again and do NOT create a new order for this link. Preserve linkId, rozoPaymentId and every tx hash, then escalate to the operator for manual reconciliation.";
55984
+ }
55985
+ if (result.unknown) {
55986
+ return "The order state could not be established. This is NOT evidence that nothing was paid \u2014 do not create a new order and do not send again on the strength of it. Retry, or pass --rozo-payment-id so the authoritative pay-in view can be read.";
55987
+ }
55988
+ if (!result.authoritativeView) {
55989
+ return "Only the fulfilment view was readable; the pay-in view is unavailable, so the money-detected rule cannot be enforced. Pass --rozo-payment-id for a complete answer.";
55990
+ }
55991
+ if ((result.state === "expired_unfunded" || result.state === "invoice_expired") && result.provider === "bitrefill") {
55992
+ return "Nothing was funded, so nothing was lost. Create a fresh Bitrefill invoice and run rozo-checkout pay --bitrefill-invoice <id> --to <0x\u2026> --amount <USDC> --with <coin>";
55993
+ }
55994
+ if (result.state === "expired_unfunded") return EXPIRED_UNFUNDED_GUIDANCE;
55995
+ return result.terminal ? "Done." : "Still in flight. Poll again in ~10s.";
55996
+ }
55980
55997
  async function main4(argv) {
55981
55998
  const args = parseArgs(argv);
55982
55999
  const rozoPaymentId = args["rozo-payment-id"] || (isRozoPaymentId(args._[0]) ? args._[0] : null);
@@ -56002,7 +56019,7 @@ async function main4(argv) {
56002
56019
  if (next.state !== result.state) history.push({ at: (/* @__PURE__ */ new Date()).toISOString(), state: next.state });
56003
56020
  result = next;
56004
56021
  }
56005
- const guidance = result.escalate ? "MONEY DETECTED and the order is not on a healthy path. Do NOT pay again and do NOT create a new order for this link. Preserve linkId, rozoPaymentId and every tx hash, then escalate to the operator for manual reconciliation." : result.unknown ? "The order state could not be established. This is NOT evidence that nothing was paid \u2014 do not create a new order and do not send again on the strength of it. Retry, or pass --rozo-payment-id so the authoritative pay-in view can be read." : !result.authoritativeView ? "Only the fulfilment view was readable; the pay-in view is unavailable, so the money-detected rule cannot be enforced. Pass --rozo-payment-id for a complete answer." : (result.state === "expired_unfunded" || result.state === "invoice_expired") && result.provider === "bitrefill" ? "Nothing was funded, so nothing was lost. Create a fresh Bitrefill invoice and run rozo-checkout pay --bitrefill-invoice <id> --to <0x\u2026> --amount <USDC> --with <coin>" : result.state === "expired_unfunded" ? "Nothing was funded, so nothing was lost. Start a fresh order with: rozo-checkout pay <coinbase-link> --with <coin> (or create-order.js --url <link> --chain <id> --token <SYMBOL>)" : result.terminal ? "Done." : "Still in flight. Poll again in ~10s.";
56022
+ const guidance = statusGuidance(result);
56006
56023
  const unresolved = watch && !result.terminal && !result.escalate && !result.unknown;
56007
56024
  const failed = result.escalate || result.unknown || !result.authoritativeView;
56008
56025
  emit(
@@ -433,7 +433,7 @@ function classifyStatus({
433
433
  }
434
434
  const exp = payment?.expiresAt ? Date.parse(payment.expiresAt) : NaN;
435
435
  if (Number.isFinite(exp) && exp < now) {
436
- return mk("expired_unfunded", "The order expired before any funds arrived. Safe to retry.", {
436
+ return mk("expired_unfunded", "The order expired before any funds arrived. This order can no longer be paid.", {
437
437
  terminal: true
438
438
  });
439
439
  }
@@ -459,7 +459,7 @@ function classifyStatus({
459
459
  case "payment_expired":
460
460
  return moneyDetected ? mk("stuck_after_payment", "Order expired AFTER funds arrived \u2014 escalate immediately.", {
461
461
  escalate: true
462
- }) : mk("expired_unfunded", "Order expired unfunded. Safe to retry.", { terminal: true });
462
+ }) : mk("expired_unfunded", "Order expired unfunded. This order can no longer be paid.", { terminal: true });
463
463
  case "payment_bounced":
464
464
  case "payment_refunded":
465
465
  return mk("stuck_after_payment", `Order ended as ${payment.status} \u2014 escalate.`, {
@@ -722,6 +722,23 @@ async function snapshot({ rozoPaymentId, linkId, provider: explicitProvider }) {
722
722
  errors: [statusError, paymentError].filter(Boolean)
723
723
  };
724
724
  }
725
+ var EXPIRED_UNFUNDED_GUIDANCE = "This order expired before any funds arrived. First check your own wallet: if anything was sent to the old deposit address, or a Lightning payment is still pending, do not pay again; contact support with the linkId and rozoPaymentId (the router cannot see a pending Lightning payment). If nothing was sent, re-run the same pay on the same link with the same --with: it creates a new order for this link. If pay answers PAYMENT_EXPIRED with retryable: true, the old order cannot be verified yet; wait a few minutes and retry. If it answers LINK_USED_OR_EXPIRED, or PAYMENT_EXPIRED with confirmed: true, this link cannot be paid any more; get a new payment link from the merchant (OpenRouter). If it answers ORDER_ALREADY_ACTIVE, a payment was found: do not pay again; contact support.";
726
+ function statusGuidance(result) {
727
+ if (result.escalate) {
728
+ return "MONEY DETECTED and the order is not on a healthy path. Do NOT pay again and do NOT create a new order for this link. Preserve linkId, rozoPaymentId and every tx hash, then escalate to the operator for manual reconciliation.";
729
+ }
730
+ if (result.unknown) {
731
+ return "The order state could not be established. This is NOT evidence that nothing was paid \u2014 do not create a new order and do not send again on the strength of it. Retry, or pass --rozo-payment-id so the authoritative pay-in view can be read.";
732
+ }
733
+ if (!result.authoritativeView) {
734
+ return "Only the fulfilment view was readable; the pay-in view is unavailable, so the money-detected rule cannot be enforced. Pass --rozo-payment-id for a complete answer.";
735
+ }
736
+ if ((result.state === "expired_unfunded" || result.state === "invoice_expired") && result.provider === "bitrefill") {
737
+ return "Nothing was funded, so nothing was lost. Create a fresh Bitrefill invoice and run rozo-checkout pay --bitrefill-invoice <id> --to <0x\u2026> --amount <USDC> --with <coin>";
738
+ }
739
+ if (result.state === "expired_unfunded") return EXPIRED_UNFUNDED_GUIDANCE;
740
+ return result.terminal ? "Done." : "Still in flight. Poll again in ~10s.";
741
+ }
725
742
  async function main(argv) {
726
743
  const args = parseArgs(argv);
727
744
  const rozoPaymentId = args["rozo-payment-id"] || (isRozoPaymentId(args._[0]) ? args._[0] : null);
@@ -747,7 +764,7 @@ async function main(argv) {
747
764
  if (next.state !== result.state) history.push({ at: (/* @__PURE__ */ new Date()).toISOString(), state: next.state });
748
765
  result = next;
749
766
  }
750
- const guidance = result.escalate ? "MONEY DETECTED and the order is not on a healthy path. Do NOT pay again and do NOT create a new order for this link. Preserve linkId, rozoPaymentId and every tx hash, then escalate to the operator for manual reconciliation." : result.unknown ? "The order state could not be established. This is NOT evidence that nothing was paid \u2014 do not create a new order and do not send again on the strength of it. Retry, or pass --rozo-payment-id so the authoritative pay-in view can be read." : !result.authoritativeView ? "Only the fulfilment view was readable; the pay-in view is unavailable, so the money-detected rule cannot be enforced. Pass --rozo-payment-id for a complete answer." : (result.state === "expired_unfunded" || result.state === "invoice_expired") && result.provider === "bitrefill" ? "Nothing was funded, so nothing was lost. Create a fresh Bitrefill invoice and run rozo-checkout pay --bitrefill-invoice <id> --to <0x\u2026> --amount <USDC> --with <coin>" : result.state === "expired_unfunded" ? "Nothing was funded, so nothing was lost. Start a fresh order with: rozo-checkout pay <coinbase-link> --with <coin> (or create-order.js --url <link> --chain <id> --token <SYMBOL>)" : result.terminal ? "Done." : "Still in flight. Poll again in ~10s.";
767
+ const guidance = statusGuidance(result);
751
768
  const unresolved = watch && !result.terminal && !result.escalate && !result.unknown;
752
769
  const failed = result.escalate || result.unknown || !result.authoritativeView;
753
770
  emit(