# Main-Wallet Payment Requests

An agent can ask, “May I send 5 USDC to this merchant?” without holding the human's keys or receiving a standing allowance. It constructs the exact transaction, opens the browser review, and waits for the human's wallet decision. Each new payment requires its own authorization.

## Resolve the Purchase

Before asking for a signature, establish the network, canonical asset denomination, exact amount, recipient, human signer, and purpose. If the merchant provides an invoice, obtain its actual collection ID and obligation reference. Check that its on-chain payouts match the agreed purchase.

“USDC” alone does not identify a network asset. Display symbols are convenience inputs, not proof of issuer or backing. Resolve the denomination and decimals through the chosen network's registry and show the resulting base units in the transaction review. Keep fees separate from the 5 USDC recipient payout.

## Pay an Existing Invoice

```bash
bb pay-requests show 46 --mainnet
bb pay-requests status 46 --mainnet
bb pay-requests pay 46 --creator "$PAYER" --obligation payment-1 --units 1 --mainnet --output-file payment.json
bb check payment.json
bb explain payment.json
bb deploy payment.json --browser --expected-address "$PAYER" --mainnet
```

`$PAYER` must be the human wallet's actual address. Replace the example IDs. The standard helper validates the collection and binds the payment to its actual approval. For a partial invoice, units are quanta that scale every payout leg; calculate the requested units from the invoice terms instead of treating them as display coins.

When the reviewed terms are already established, the inline equivalent is:

```bash
bb pay-requests pay 46 --creator "$PAYER" --obligation payment-1 --units 1 --browser --mainnet
```

A merchant or manager must first publish the invoice collection. An agent can prepare its creation transaction, but cannot assume an unpublished collection has a known ID or that invoice creation itself requires no signature. A direct transfer is available when a persisted invoice is unnecessary.

## Direct Coin Transfer

```bash
bb build send --from "$PAYER" --to "$RECIPIENT" --amount 5 --denom USDC --mainnet --output-file payment.json
bb explain payment.json
bb deploy payment.json --browser --expected-address "$PAYER" --mainnet
```

The inline form is `bb build send --from "$PAYER" --to "$RECIPIENT" --amount 5 --denom USDC --mainnet --browser`. The `send` builder uses `--from` as the expected signer. Verify the resolved asset and amount before proceeding.

This is a bank transfer, not an invoice collection. It does not create invoice obligations, progress counters, refund rights, or recurring consent. Use [invoice standards](https://docs.bitbadges.io/standards/payments) when those finite payment-tracking semantics are needed.

## What the Browser Binds

The versioned transaction request carries a request ID, expected signer, deployment network, Cosmos and EVM chain IDs, expiration, signing mode, and transaction messages. The page validates the request and supported message types. Explicit sender fields are preserved; omitted sender fields are populated only from the expected signer.

The normalized messages shown for review must be the messages passed to the wallet. Wallet address, selected network, request expiration, and reviewed message identity are checked again before signing. A transaction review must not silently add a login transaction or replace an explicit sender with the currently connected account.

The new page also accepts supported legacy CLI requests through a separate adapter. Supplied signer and chain fields are preserved and checked; missing values are pinned once from the selected wallet and page network for that review, with a finite page lifetime. Legacy requests cannot retroactively prove the original CLI network or an omitted expiry.

This binding protects the application's handoff. It does not prove that a merchant's prose description is true or that delivery will occur. Local and mainnet configurations can share a Cosmos chain ID; the application's deployment label is not a cryptographic replay boundary in raw Cosmos signed bytes.

## Wallet Decision and Fees

Give the person a short handoff before launching the browser: “Pay this invoice on mainnet from your wallet: 5 USDC to the reviewed merchant address. This is one payment, with no recurring allowance. Review the separate network fee in your wallet.” Use the actual proposal's terms; if it grants an allowance or has multiple recipients, describe those instead.

Keep the CLI running until it receives the result. Use `--no-open` to print the signing URL when automatic opening is inconvenient. Open it in a browser on the same machine as the CLI, or use the documented SSH port forwarding. The callback uses localhost, so sending the link to a phone or closing the terminal can prevent the result from returning even after a successful payment.

The human reviews all messages and confirms in the wallet. The frontend selects gas and fees at signing time. Browser `--fee`, `--fee-denom`, and `--gas` flags do not impose a fee cap; those CLI controls belong to other signing paths. Review the wallet's fee request separately from recipient payouts.

Use ordinary sign-and-broadcast for payments. `--sign-only` is for compatible Cosmos adapters returning raw signed bytes. EVM paths that send during signing are rejected before invoking the wallet. The current callback transport accepts at most 4096 base64 characters of signed bytes; larger results return an explicit error and must use another supported signing flow. Do not treat this callback as a general large-transaction export channel.

Declining before wallet dispatch means no wallet signing request should begin. Once wallet interaction is in flight, closing a page is not proof of cancellation or non-submission. A request expiry prevents starting another signing invocation; it does not revoke an already signed or submitted transaction.

## Confirm the Result

Browser callbacks distinguish signing, submission, cancellation, error, and an unknown submission outcome. `outcome: "unknown"` includes `retrySafe: false`; reconcile it before another attempt. Submission is returned with `confirmed: false` and `verification: "unverified"`. The CLI validates the returned request identity, signer, network, and mode, but does not independently prove the signature contents or successful chain execution from the callback alone.

```bash
bb tx status "$TX_HASH" --mainnet
bb tx wait "$TX_HASH" --mainnet --timeout 120
bb pay-requests status 46 --mainnet
```

Inspect the chain execution result. The indexer may need time to reflect the confirmed payment. Store the hash and invoice obligation reference so a lost callback can be reconciled without paying again. On a timeout or ambiguous wallet error, inspect wallet activity and chain status before retrying. Reusable links intentionally accept repeat payments.

| Observed result | Report to the person | Next step |
| --- | --- | --- |
| Unsigned proposal | Ready for review | Review terms before requesting a wallet signature |
| Signed bytes | Signed, not submitted by this flow | Broadcast only through an authorized signing workflow |
| Submitted hash | Submitted; confirmation pending | Inspect chain execution, then invoice progress |
| Confirmed execution, stale invoice view | Confirmed; dashboard catching up | Wait for indexing; do not pay again |
| Declined before wallet dispatch | Request declined | Leave the payment unsubmitted |
| Timeout, lost callback, or uncertain wallet error | Outcome unknown | Reconcile wallet activity and chain state before another attempt |

### Recover a Request

The CLI saves browser transaction requests and their callbacks in private local files before opening the signing page. It prints the request ID on stderr. Inspect them from a second terminal:

```bash
bb dev requests list
bb dev requests status "$REQUEST_ID"
bb dev requests resume "$REQUEST_ID"
```

`status` reports the recorded result and checks the original listener. `resume` returns the **same** `signUrl` only while that listener is alive and the request has not expired or completed. Keep the original CLI running; this is not a background signing service. Neither command submits a transaction or creates a replacement request. Missing or expired listeners produce `outcome: "unknown"`, `canResume: false`, and `retrySafe: false`.

Recorded callbacks remain unverified: a saved hash is not proof of successful execution. Use `bb tx status` / `bb tx wait` on the original network, then reconcile invoice or subscription state. Request files contain transaction details and signing links; keep them private. They live under the CLI configuration directory (`~/.bitbadges/signing-requests` by default; `BITBADGES_CONFIG_DIR` selects a separate directory). Restarting `deploy --browser` creates a new request, so never use it as an automatic retry after uncertainty.

## Recurring Consent Is Separate

A personal-sign message such as “I authorize this agent” does not install an on-chain spending approval. A successful invoice payment does not authorize the next purchase. A payment link is not automatic billing.

Use [Subscriptions](https://docs.bitbadges.io/standards/subscriptions) when the human intentionally authorizes recurring charges, and inspect its period, recipient, amount, expiry, and cancellation semantics separately. [Spending Authorization](https://docs.bitbadges.io/agents/spending-authorization) covers a distinct delegate-wallet design. Neither is required for the main-wallet request-per-payment flow.
