@tuwaio/quasar-sdk 0.7.2 → 0.8.0

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,9 +1,9 @@
1
1
  # @tuwaio/quasar-sdk
2
2
 
3
3
  [![NPM Version](https://img.shields.io/npm/v/@tuwaio/quasar-sdk.svg)](https://www.npmjs.com/package/@tuwaio/quasar-sdk)
4
- [![License](https://img.shields.io/npm/l/@tuwaio/quasar-sdk.svg)](https://github.com/TuwaIO/sdk/blob/main/packages/quasar-sdk/LICENSE)
4
+ [![License](https://img.shields.io/npm/l/@tuwaio/quasar-sdk.svg)](https://github.com/TuwaIO/quasar-client/blob/main/packages/quasar-sdk/LICENSE)
5
5
 
6
- `@tuwaio/quasar-sdk` is the Layer 5 (L5) package of the **TUWA SDK**: the client of the API of **Quasar**, the TUWA backend that tracks the transactions of your app on the server and keeps their history. It works with Quasar Cloud (`https://api.tuwa.io`) and with a self-hosted Quasar server. It has three parts: the `Quasar` client for your server, a check for the browser (`@tuwaio/quasar-sdk/react`), and the `quasar-sdk` CLI that relays webhooks to `localhost`.
6
+ `@tuwaio/quasar-sdk` is the client of the API of **Quasar**, the TUWA backend that tracks the transactions of your app on the server, keeps their history and, for a Payments app, issues invoices paid in crypto straight to your wallets. It works with Quasar Cloud (`https://api.tuwa.io`) and with a self-hosted Quasar server. It has four parts: the `Quasar` client for your server (with webhook verification), the headless checkout for the browser (`@tuwaio/quasar-sdk/checkout`), a check for the browser (`@tuwaio/quasar-sdk/react`), and the `quasar-sdk` CLI that relays webhooks to `localhost`.
7
7
 
8
8
  ---
9
9
 
@@ -11,7 +11,11 @@
11
11
 
12
12
  - **Transaction sync:** `quasar.pulsar.syncCreate` sends a transaction created by Pulsar to Quasar, which tracks it until it reaches a final status (so the status survives a closed tab) and sends your webhooks.
13
13
  - **History:** `quasar.pulsar.getHistory` returns the transactions of your app, newest first, filtered by wallet address, chain, status, transaction key or application name.
14
- - **Errors:** every failed request throws a `QuasarSDKError` with the HTTP `status`.
14
+ - **EIP-5792 batches:** a batch sent with `wallet_sendCalls` is synced by its batch ID; `watchBatchHashes` reads the hash of its transaction from the Pulsar store in the browser, and `quasar.pulsar.syncHash` sends it to Quasar from the server.
15
+ - **Payments:** `quasar.payments` issues invoices (with their PDF and e-invoice documents and a payment page), lists and reads them with their hash-chained ledger, cancels, releases and corrects them, refunds payments, prices amounts, and runs subscriptions billed every period.
16
+ - **Headless checkout:** `createCheckoutStore` from `@tuwaio/quasar-sdk/checkout` follows the payment of one invoice in the buyer's browser (methods, the quote, AML-screened when the merchant checks paying wallets, buyer details, language, the transaction or gasless signature, live status) with its checkout token and no key; `createRefundStore` refunds a payment from the merchant's wallet through calls the app runs on its server. Neither sends a transaction: Pulsar or the wallet does.
17
+ - **Webhook verification:** `verifyWebhook` checks the signature of a webhook and the time it was sent (`sentAt`, or `timestamp` for a transaction webhook of an older engine), and returns its typed body.
18
+ - **Errors:** every failed request throws a `QuasarSDKError` with the HTTP `status` and, from the Payments API, a stable `code` and the fields at fault (`issues`).
15
19
  - **Pre-flight check:** `preFlightTxCheck` from `@tuwaio/quasar-sdk/react` stops a Pulsar transaction in the browser when the user is not signed in with SIWX or the Quasar API does not respond.
16
20
  - **Webhook relay:** `npx @tuwaio/quasar-sdk listen` receives the deliveries of a webhook endpoint with a `localhost` URL and posts them to your local app, without a tunnel.
17
21
 
@@ -20,15 +24,19 @@
20
24
  ## 💾 Installation
21
25
 
22
26
  ```bash
23
- pnpm add @tuwaio/quasar-sdk @tuwaio/pulsar-core
27
+ pnpm add @tuwaio/quasar-sdk
28
+ # To sync Pulsar transactions:
29
+ pnpm add @tuwaio/pulsar-core
24
30
  ```
25
31
 
26
- | Import path | Provides | Peer dependencies |
27
- | -------------------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------- |
28
- | `@tuwaio/quasar-sdk` | `Quasar`, `PulsarModule`, `watchBatchHashes`, `QuasarSDKError`, the endpoint constants and types | `@tuwaio/pulsar-core` (>=0.10), for the transaction types |
29
- | `@tuwaio/quasar-sdk/react` | `preFlightTxCheck` | Also `@tuwaio/siwx-react` (>=0.5, optional for the root) |
32
+ | Import path | Provides | Peer dependencies |
33
+ | ----------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
34
+ | `@tuwaio/quasar-sdk` | `Quasar`, `PulsarModule`, `PaymentsModule`, `verifyWebhook`, `QuasarSDKError`, the endpoint constants and types | `@tuwaio/pulsar-core` (>=0.10, optional), for the transaction types |
35
+ | `@tuwaio/quasar-sdk/pulsar` | `TransactionStatus`, `TransactionTracker`, `watchBatchHashes` | `@tuwaio/pulsar-core` (>=0.10) |
36
+ | `@tuwaio/quasar-sdk/checkout` | `createCheckoutStore`, `createRefundStore` and their types | Also `zustand` (5.x, optional for the other entries) |
37
+ | `@tuwaio/quasar-sdk/react` | `preFlightTxCheck` | Also `@tuwaio/siwx-react` (>=0.5, optional for the root) |
30
38
 
31
- The root entry point imports neither React nor SIWX packages, so it runs in Node.js, Next.js Server Actions and route handlers, and Edge runtimes. Its HTTP client, `ofetch`, is a dependency.
39
+ The root entry point imports neither React, SIWX, Pulsar nor `zustand`, so it runs in Node.js, Next.js Server Actions and route handlers, and Edge runtimes. Its HTTP client, `ofetch`, is a dependency.
32
40
 
33
41
  ---
34
42
 
@@ -68,12 +76,94 @@ export async function syncBatchHash(txKey: string, hash: `0x${string}`) {
68
76
  ```
69
77
 
70
78
  ```ts
71
- import { watchBatchHashes } from '@tuwaio/quasar-sdk';
79
+ import { watchBatchHashes } from '@tuwaio/quasar-sdk/pulsar';
72
80
 
73
81
  // In the browser, next to the Pulsar store
74
82
  const stop = watchBatchHashes(pulsarStore, (tx) => syncBatchHash(tx.txKey, tx.hash));
75
83
  ```
76
84
 
85
+ ### Payments
86
+
87
+ A Payments app (chosen when the app is created, on a node that runs Payments) issues invoices that buyers pay in crypto on its payment page; Quasar checks the payment on-chain, issues the receipt and sends `payments.v1` webhooks.
88
+
89
+ ```ts
90
+ import { Quasar } from '@tuwaio/quasar-sdk';
91
+
92
+ const quasar = new Quasar({ secretKey: process.env.QUASAR_SECRET_KEY ?? '' });
93
+
94
+ export async function checkout(orderId: string, email: string) {
95
+ const { payUrl } = await quasar.payments.createInvoice(
96
+ {
97
+ currency: 'EUR',
98
+ lineItems: [{ name: 'Pro plan, October', quantity: '1', unitPrice: '49.00' }],
99
+ buyer: { email },
100
+ metadata: { orderId },
101
+ },
102
+ { idempotencyKey: `order_${orderId}` },
103
+ );
104
+ return payUrl;
105
+ }
106
+ ```
107
+
108
+ Verify every webhook before acting on it, with the raw body as received:
109
+
110
+ ```ts
111
+ import { isPaymentWebhookEvent, verifyWebhook } from '@tuwaio/quasar-sdk';
112
+
113
+ export async function POST(request: Request) {
114
+ try {
115
+ const event = await verifyWebhook({
116
+ body: await request.text(),
117
+ signature: request.headers.get('x-quasar-signature'),
118
+ secret: process.env.QUASAR_WEBHOOK_SECRET ?? '',
119
+ });
120
+ if (isPaymentWebhookEvent(event) && event.type === 'invoice.paid') {
121
+ console.log('Paid', event.data.invoice?.number); // fulfil the order; deduplicate by event.id
122
+ }
123
+ return new Response(null, { status: 204 });
124
+ } catch {
125
+ return new Response(null, { status: 400 });
126
+ }
127
+ }
128
+ ```
129
+
130
+ `verifyWebhook` refuses a delivery sent further from now than `toleranceSeconds` (default 300) as `stale`, so a captured webhook cannot be replayed later. It reads `sentAt`, set on every delivery attempt; a transaction webhook from an engine that does not send `sentAt` yet is checked by its `timestamp`, the time it was created, which its retries reuse: raise `toleranceSeconds` (1200 covers the retries) until the engine is updated. `toleranceSeconds: false` turns the check off.
131
+
132
+ `invoice.held` carries `data.hold`: why (`reason`: `late`, `aml`, `quote_expired`), its `txHash` and `senders`. A transfer that reached an invoice without being tied to it by proof never holds the invoice: Quasar records it as a held transfer of its own and sends `invoice.transfer_held` (`data.heldTransfer`: its `id`, `txHash`, `amount` in base units, `senders`, `reason`: `payer_mismatch`, `payer_unconfirmed`, `already_paid`, `quote_changed` or `too_many_parts`). List them with `listHeldTransfers` (`{ status: 'held' }` for those still to refund, `{ invoice }` for one invoice) and refund one as a whole to the wallet that sent it with `refundHeldTransfer(id)`, then `submitRefund` like any refund; the refund's `heldTransfer` names it. `invoice.transfer_hold_voided` tells you that the same transaction was proven to pay another invoice of yours since (`data.heldTransfer.paidInvoice`): nothing to refund. `payment.unverified` tells you that a smart wallet sent a native coin inside its own call, which no receipt shows: nothing was credited, so check the transaction yourself; a smart wallet is offered tokens only.
133
+
134
+ ### Checkout in the browser
135
+
136
+ The payment page of an invoice is its `payUrl`; to embed the checkout in your own page instead, pass its `checkoutToken` to the checkout store. The store holds where the payment stands; the wallet sends the transaction (with Pulsar, or `@tuwaio/nova-payments`, which renders the store).
137
+
138
+ ```ts
139
+ import { createCheckoutStore } from '@tuwaio/quasar-sdk/checkout';
140
+
141
+ const checkout = createCheckoutStore({ token: checkoutToken });
142
+ await checkout.getState().load();
143
+
144
+ const { checkout: view } = checkout.getState();
145
+ checkout.getState().selectMethod(view?.methods[0]?.id ?? '');
146
+ checkout.getState().setPayer('eip155:8453:0x1111111111111111111111111111111111111111');
147
+ // An EVM payment the buyer's wallet sends: the wallet first confirms the invoice with a free signature
148
+ if (checkout.getState().payerProof === 'required') {
149
+ await checkout.getState().confirmPayer((message) => wallet.signMessage({ message }));
150
+ }
151
+ const quote = await checkout.getState().requestQuote();
152
+ // Send quote.instructions (the amount in base units to `to`) with the wallet, then hand over its hash:
153
+ await checkout.getState().submit({ txKey: '0x…' });
154
+ checkout.subscribe(({ phase }) => console.log(phase)); // confirming, then paid
155
+ ```
156
+
157
+ The page's origin must be one of the domains of your Quasar app, when the app lists any.
158
+
159
+ Quasar credits a transfer only to an invoice it is tied to by proof. On Solana the quote's reference is the proof; a gasless payment through `relay` is proven by the EIP-3009 authorization the wallet signs. For an EVM payment the buyer's wallet sends (paying the gas, or a smart wallet with or without the merchant's paymaster), the wallet confirms the invoice first, right after the wallet and the method are chosen and before the price: `payerProof` is `required`, `requestQuote()` refuses with `payer_proof_required` until then, and `confirmPayer(sign)` asks Quasar for the exact Sign-In with Ethereum message (it names the page's site, the invoice number, the seller and the total), has `sign` sign it with the wallet (`personal_sign`: free, it moves no funds) and sends the signature, which Quasar checks (a smart wallet's through its contract) and records. `payerProof` is then `confirmed`. One confirmation per invoice and wallet: a new quote, another token or network needs none (a smart wallet's counts on its network only), also on a reopened page. For a method the gasless relay may pay, `payerProof` is `unless_relayed`: the price comes first, and only a transfer or a paymaster payment needs `confirmPayer` before the wallet sends it. A transfer from a wallet that did not confirm the invoice, or from another wallet than the quoted one, pays no invoice: Quasar records it as a held transfer, which the merchant returns to the wallet that sent it, and the invoice stays payable (the rejected payment carries `held`, and so does the store's `payment_mismatch` error): say that the merchant returns it to that wallet and that the invoice can still be paid from the confirmed wallet, never that the merchant checks the payment.
160
+
161
+ `paymentOnTheWay` is `true` from a successful `submit` or `relay` until the payment settles or fails: use it, not `txKey`, to tell the buyer a payment is on its way (a relay Quasar answers with `sending` has no `txKey` yet). When Quasar rejects that payment for good, the store goes back to the payment, even though the invoice stays `open` (to the methods when the locked price expired meanwhile), with `error` `payment_failed` when the transaction did not go through (reverted, cancelled) or `payment_mismatch` when it went through without paying the invoice (a wrong amount or recipient, sent before the quote, already used): it may have moved money, so tell the buyer that this transaction does not pay the invoice and to contact the merchant if money left the wallet, never that nothing was charged. When Quasar could not confirm it but the money may still have left the wallet (the network never returned the transaction, no receipt in time), `phase` becomes `unconfirmed` with `error` `payment_unconfirmed`: ask the buyer to check the wallet and offer no payment; `payAgain()` goes back to it once they did. Promise that Quasar checks the payment again (for up to 24 hours) only when `error.rechecked` is `true`; otherwise (a relay operation lost, `transaction_failed`) Quasar never reads it again, so ask the buyer to contact the merchant with the transaction hash if money left the wallet. A transaction that moved money without paying the invoice is `payment_mismatch` whether or not Quasar calls it final; when it is not final, `phase` stays `unconfirmed` too. A transaction sped up in the wallet is followed by Quasar under its new hash and is not rejected. When `submit` gets no answer (the network, a busy or failing server), the wallet has sent the transaction all the same: `submit` returns `false`, `phase` is `unconfirmed` with `error.reason` `submit_retrying`, and the store hands the same transaction over again with a growing pause (up to an hour, until `destroy`), then follows it; after the hour `error.reason` is `submit_failed` (contact the merchant with the transaction hash). Until Quasar takes or refuses it, the hand-over is kept in the tab, and the next `load()` of the same checkout (a reload, the page opened again in that tab) hands it over again. When another invoice's page handed the same transaction over first (anyone who saw the hash can), Quasar answers `409 tx_already_used`, records this invoice's claim and credits the transaction to the invoice the wallet that sent it confirmed: `phase` is `unconfirmed` with `error.reason` `tx_already_used`, the store follows the transaction and `payAgain()` does nothing until Quasar decides (the invoice then becomes `processing` or `paid`, or the transaction is rejected here with `tx_already_used` as `payment_mismatch`). Never offer a second payment for it. A payment the network confirmed that Quasar has not recorded yet (`error.reason` `settlement_failed`) is `unconfirmed` too, with no second payment: ask the buyer to contact the merchant with the transaction hash, never say that it does not pay the invoice; say that Quasar tries again daily only while `error.rechecked` is `true` (for 30 days after it learned of the payment).
162
+
163
+ `invoicePaymentOnTheWay` is `true` while Quasar reports a payment of the invoice on its way that this page may not have handed over (the page was reloaded or opened again, or Quasar found a Solana Pay transfer): the store then starts in, or moves to, `confirming` instead of offering to pay, and follows that payment as its own. `paymentCountsUntil` is Quasar's word that a payment sent before `dueAt` is on its way, and until when the invoice waits for it: `paymentSentInTime` says it for the payment this page handed over (`true` once Quasar lists it among the payments sent in time, `false` when Quasar holds it as handed over after `dueAt`): use them, not the browser's clock, to say that the payment was sent in time. `invoicePaymentUnresolved` is `true` while Quasar reports a payment of the invoice that may still arrive, with no time limit (one stuck or one Quasar reads again for 24 hours): never say that nothing was charged then; a reopened page that finds no payment on its way but the latest one unconfirmed or unresolved starts in `unconfirmed` (an expired invoice stays `expired` with `error` `payment_unconfirmed`).
164
+
165
+ The deadline is Quasar's: the store never ends a confirming payment by the clock. When the invoice expires while `paymentOnTheWay` (or `invoicePaymentOnTheWay`), `phase` becomes `expired` and the store keeps following the invoice: the payment may still make it `paid` (Quasar waits up to 30 minutes for a payment it learned of before `dueAt`) or `held` (a late payment the merchant accepts or returns), so tell the buyer their payment may still arrive rather than that nothing was charged. It keeps the event stream while Quasar keeps it open for that payment, and otherwise reads the invoice every 20 seconds; it stops at `followingUntil` (35 minutes past the later of `dueAt` and the latest hand-over, or the time a reopened page found the payment on its way), or once Quasar reports no payment on its way, and `paymentOnTheWay` is then `false`. A cancelled invoice is followed the same way while a payment is on its way (Quasar holds it for the merchant), for 35 minutes after the later of when the store found it cancelled and the latest hand-over. Past `followingUntil` the page learns nothing more until it is reloaded: tell the buyer until when this page follows the payment, not that it shows the outcome whenever it comes.
166
+
77
167
  ### Webhook relay
78
168
 
79
169
  Add a webhook endpoint with a `localhost` URL in the Quasar dashboard, put its signing secret in `.env.local` and start the relay next to your dev server:
@@ -98,24 +188,25 @@ The relay posts each delivery with the `x-quasar-signature`, `x-quasar-event` an
98
188
 
99
189
  ## 🗄️ Browser Storage
100
190
 
101
- Nothing is written. `preFlightTxCheck` reads the SIWX session from the store of `@tuwaio/siwx-react`, which keeps it in `localStorage` under `siwx-react:session`.
191
+ The checkout store keeps a transaction the wallet sent until Quasar takes or refuses it, so that a page closed or reloaded before Quasar answered hands it over again on its next `load()`: in `sessionStorage` (the browser tab, until it closes) under `quasar-sdk:checkoutHandOvers:<checkout token>`, a JSON array of `{ txKey, from?, connectorType?, at }` (the transaction hash or signature, the sending wallet and the wallet connector as passed to `submit`, and when the store first got it, in milliseconds). The entry is removed once Quasar takes or refuses the transaction; pass `handOverStorage: null` to `createCheckoutStore` to keep nothing (the store keeps nothing either when you pass your own `api`). The refund store keeps a transaction the wallet sent the same way, in `sessionStorage` under `quasar-sdk:refundHandOvers`, a JSON array of `{ refundId, invoiceId, instructions, txHash, from }`, until Quasar takes it or refuses it for good; pass `handOverStorage: null` to `createRefundStore` to keep it in memory only. Everything else of the checkout and refund stores stays in memory. `preFlightTxCheck` reads the SIWX session from the store of `@tuwaio/siwx-react`, which keeps it in `localStorage` under `siwx-react:session`.
102
192
 
103
193
  ## 🌐 External Services
104
194
 
105
- | Part | Host | Request |
106
- | ------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
107
- | `Quasar` client | `baseUrl` (default `https://api.tuwa.io`) | `POST /v1/engine/pulsar/sync`, `POST /v1/engine/pulsar/sync/:txKey/hash` and `GET /v1/engine/pulsar/history`, with the secret key in the `x-tuwa-secret-key` header |
108
- | `preFlightTxCheck` | Its `customApiUrl` (default `https://api.tuwa.io`) | `GET /v1/engine/monitoring/health`, without credentials |
109
- | `quasar-sdk listen` | `--api-url` (default `https://api.tuwa.io`), then `--forward-to` | A Server-Sent Events stream from `/v1/engine/webhooks/listen` with the signing secret in the `x-webhook-secret` header; a `POST` to the local URL for each delivery |
195
+ | Part | Host | Request |
196
+ | ------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
197
+ | `Quasar` client | `baseUrl` (default `https://api.tuwa.io`) | `POST /v1/engine/pulsar/sync`, `POST /v1/engine/pulsar/sync/:txKey/hash`, `GET /v1/engine/pulsar/history` and the Payments API under `/v1/payments`, with the secret key in the `x-tuwa-secret-key` header |
198
+ | Checkout stores | `baseUrl` (default `https://api.tuwa.io`) | The checkout routes `/v1/payments/checkout/:token` and their `events` stream, with the token in the path and no key; the refund store calls only the functions you pass |
199
+ | `preFlightTxCheck` | Its `customApiUrl` (default `https://api.tuwa.io`) | `GET /v1/engine/monitoring/health`, without credentials |
200
+ | `quasar-sdk listen` | `--api-url` (default `https://api.tuwa.io`), then `--forward-to` | A Server-Sent Events stream from `/v1/engine/webhooks/listen` with the signing secret in the `x-webhook-secret` header; a `POST` to the local URL for each delivery |
110
201
 
111
- The transactions you sync, with their `payload`, are stored by Quasar.
202
+ The transactions you sync, with their `payload`, are stored by Quasar, and so are the invoices you issue with their buyer details. `verifyWebhook` and `watchBatchHashes` send no requests.
112
203
 
113
204
  ---
114
205
 
115
206
  ## 📚 API Reference
116
207
 
117
- Every export, with signatures and types generated from the source, is documented at **[sdk.docs.tuwa.io/packages/quasar-sdk](https://sdk.docs.tuwa.io/packages/quasar-sdk)**. The HTTP API is described in the **[Quasar API reference](https://docs.tuwa.io/quasar/api)**.
208
+ Every export, with signatures and types generated from the source, is documented at **[payments.docs.tuwa.io](https://payments.docs.tuwa.io/?path=/docs/packages-quasar-sdk-overview--docs)**. The HTTP API is described in the **[Quasar API reference](https://docs.tuwa.io/quasar/api)**.
118
209
 
119
210
  ## 📄 License
120
211
 
121
- Licensed under the **Apache-2.0 License**. See the [LICENSE](https://github.com/TuwaIO/sdk/blob/main/packages/quasar-sdk/LICENSE) file for details.
212
+ Licensed under the **Apache-2.0 License**. See the [LICENSE](https://github.com/TuwaIO/quasar-client/blob/main/packages/quasar-sdk/LICENSE) file for details.
@@ -0,0 +1 @@
1
+ 'use strict';var chunkLGJMFD5H_cjs=require('./chunk-LGJMFD5H.cjs'),chunk2LAAWGEK_cjs=require('./chunk-2LAAWGEK.cjs'),vanilla=require('zustand/vanilla'),ofetch=require('ofetch');function _e(){try{return globalThis.sessionStorage??null}catch{return null}}function sn(t){return async(...s)=>{try{return await t(...s)}catch(c){if(!(c instanceof chunkLGJMFD5H_cjs.a)||!c.code)throw c;return {refused:{code:c.code,message:c.message,status:c.status}}}}}var Ae="quasar-sdk:refundHandOvers",gt=5*6e4,St=3e4,kt=new Set([401,403,408,425,429]),_t=({status:t})=>t!==void 0&&t>=400&&t<500&&!kt.has(t);function X(t){if(t&&typeof t=="object"&&"refused"in t)throw Object.assign(new Error(t.refused.message),t.refused);return t}function Z(t){if(t instanceof chunkLGJMFD5H_cjs.a){let c=t.details?.invoice;return {code:t.code??"request_failed",message:t.message,status:t.status,issues:t.issues,...typeof c=="string"?{otherInvoice:c}:{}}}let s=t;return {code:typeof s?.code=="string"?s.code:"request_failed",message:t instanceof Error?t.message:String(t),...typeof s?.status=="number"&&{status:s.status},...typeof s?.text=="string"&&{text:s.text}}}function an(t){let s=t.pollMs??5e3,c=null,y=t.handOverStorage!==void 0?t.handOverStorage:_e(),S=()=>{c&&clearTimeout(c),c=null;},v=()=>{try{let g=JSON.parse(y?.getItem(Ae)??"[]");return Array.isArray(g)?g:[]}catch{return []}},b=g=>{try{g.length>0?y?.setItem(Ae,JSON.stringify(g)):y?.removeItem(Ae);}catch{}},q=g=>b(v().filter(C=>C.refundId!==g));return vanilla.createStore()((g,C)=>{let L=l=>{S();let m=Date.now(),P=()=>{let T=Date.now()-m<gt?s:Math.max(s,St),E=setTimeout(()=>{t.get(l).then(X).then(O=>{c!==E||C().refund?.id!==l||(O.status==="confirmed"||O.status==="failed"?(S(),g({refund:O,phase:O.status})):(g({refund:O}),P()));},O=>{if(c!==E)return;let{status:U}=Z(O);U===401||U===403||U===404?S():P();});},T);c=E;};P();};return {phase:"idle",refund:null,instructions:null,error:null,sentTransaction:null,preview:async(l,m={})=>{if(g({error:null}),!t.preview)return null;try{return X(await t.preview(l,m))}catch(P){return g({error:Z(P)}),null}},start:async(l,m={})=>{S(),g({phase:"requesting",error:null,refund:null,instructions:null,sentTransaction:null});let P=v().find(T=>T.invoiceId===l);if(P)try{let T=X(await t.get(P.refundId));if(T.status==="requested"){let{txHash:E,from:O,instructions:U}=P;return g({phase:"awaitingTransfer",refund:T,instructions:U,sentTransaction:{txHash:E,from:O}}),!0}if(q(P.refundId),T.status==="submitted")return g({phase:"confirming",refund:T}),L(T.id),!0}catch(T){let E=Z(T);if(E.status!==404)return g({phase:"idle",error:E}),false;q(P.refundId);}try{let{refund:T,instructions:E}=X(await t.request(l,m));return g({phase:"awaitingTransfer",refund:T,instructions:E}),!0}catch(T){return g({phase:"idle",error:Z(T)}),false}},resume:(l,m)=>{S();let P=v().find(E=>E.refundId===l.id),T=P?{txHash:P.txHash,from:P.from}:C().refund?.id===l.id?C().sentTransaction:null;g({phase:"awaitingTransfer",refund:l,instructions:m,error:null,sentTransaction:T});},recheck:async()=>{let l=C().refund;if(!l)return false;try{let m=X(await t.get(l.id));if(C().refund?.id!==l.id)return !1;if(m.status==="requested"){let P=C().instructions;return P&&m.cryptoAmount&&m.cryptoAmount!==P.amount&&!C().sentTransaction?(g({refund:m,instructions:{...P,amount:m.cryptoAmount},error:{code:"refund_repriced",message:"Quasar priced this refund again: check the new amount"}}),!1):(g({refund:m,error:null}),!C().sentTransaction)}return q(l.id),m.status==="submitted"?(g({phase:"confirming",refund:m,error:null,sentTransaction:null}),L(l.id)):g({phase:m.status,refund:m,error:null,sentTransaction:null}),!1}catch(m){return g({error:Z(m)}),false}},submit:async l=>{let m=C().refund;if(!m)return g({error:{code:"refund_required",message:"Ask for the refund first"}}),false;let P={txHash:l.txHash,from:l.from},T=C().instructions;T&&b([...v().filter(E=>E.refundId!==m.id),{refundId:m.id,invoiceId:m.invoiceId,instructions:T,...P}]),g({phase:"submitting",error:null,sentTransaction:P});try{let E=X(await t.submit(m.id,l));return q(m.id),g({phase:"confirming",refund:E,sentTransaction:null}),L(m.id),!0}catch(E){let O=Z(E);return _t(O)?(q(m.id),g({phase:"awaitingTransfer",error:O,sentTransaction:null})):g({phase:"awaitingTransfer",error:O}),false}},stopFollowing:S,keepFollowing:()=>{let{phase:l,refund:m}=C();l==="confirming"&&m&&!c&&L(m.id);},reset:()=>{S(),g({phase:"idle",refund:null,instructions:null,error:null,sentTransaction:null});}}})}var wt=45e3,vt=9e4,Qe=(t,s="")=>`/v1/payments/checkout/${encodeURIComponent(t)}${s?`/${s}`:""}`;function Ge(t,s=chunk2LAAWGEK_cjs.a){let c=async(y,S,v=wt)=>{try{return await ofetch.ofetch(Qe(t,y),{baseURL:s,method:S?"POST":"GET",timeout:v,...S?{body:S}:{}})}catch(b){throw chunkLGJMFD5H_cjs.b(b)}};return {view:()=>c(""),quote:y=>c("quote",y),payerProofMessage:y=>c("payer-proof/message",y),payerProof:y=>c("payer-proof",y),buyer:y=>c("buyer",y),locale:y=>c("locale",{locale:y}),submit:async({methodId:y,...S})=>{if(!y)return c("submit",S);try{return await c("submit",{...S,methodId:y})}catch(v){if(!(v instanceof chunkLGJMFD5H_cjs.a)||v.status!==400)throw v;return c("submit",S)}},relay:y=>c("relay",{signature:y},vt),permission:y=>c("permission",y),permissionRevoked:()=>c("permission/revoked",{}),url:y=>`${s.replace(/\/+$/,"")}${Qe(t,y)}`}}var st=new Set(["paid","held","expired","cancelled","refunded","partially_refunded"]),ee=new Set(["paid","held","refunded","partially_refunded"]),Ke=new Set(["open","processing","underpaid","expired","cancelled"]),N=new Set(["expired","cancelled"]),V=new Set(["open","processing","underpaid"]),Pe=new Set(["loading","selectMethod","awaitingPayment","underpaid","unconfirmed"]),Et=25*6e4,Rt=35*6e4,Ct=35*6e4,xt=60*6e4,Be=2e4,bt=3*6e4,Ot=45e3,It=1e4,Ve=(t,s)=>t===s||Date.parse(t??"")===Date.parse(s??""),At=new Set(["quoting","submitting"]),Ye=new Set(["checkout_not_found","origin_not_allowed","payments_disabled"]),Kt=new Set(["nonce_spent_unexplained","no_matching_transfer","reference_missing","too_early","tx_already_used","payer_mismatch","payer_unconfirmed","already_paid","quote_changed","too_many_parts","too_many_transfers","below_minimum","native_from_contract_unverifiable","invoice_not_payable","settlement_failed"]),Me="settlement_failed",de="nonce_spent_unexplained",Te="tx_already_used",at="too_many_payments",qt=[6e4,5*6e4,15*6e4],it=new Set(["timeout","not_found","replaced","nonce_spent"]),Mt="quasar-sdk:checkoutHandOvers:",Lt=new Set(["payer_mismatch","payer_unconfirmed"]),Ut="quote_changed",ut=new Set(["eoa","authorization"]);function ve(t){let[s,c,y,...S]=t.split(":");return !s||!c||!y||S.length>0?null:{namespace:s,chainId:`${s}:${c}`,address:s==="eip155"?y.toLowerCase():y}}var $e="The wallet did not sign the confirmation. It is free and moves no funds: sign it to pay from this wallet, or choose another wallet or method.",Dt=new Set(["payer_chain_mismatch","too_many_payers","native_from_contract","payer_blocked","payer_not_expected"]);function Nt(t){let s=t?.code;return s!==void 0&&(s.startsWith("payer_proof_")||Dt.has(s))}function Ht(t,s){let c=ve(s);return c?t.some(y=>{let S=ve(y.payer);return !S||S.namespace!==c.namespace||S.address!==c.address?false:y.kind&&ut.has(y.kind)||y.chainId===c.chainId}):false}var Je=[2e3,4e3,8e3,16e3,3e4],Wt=60*6e4,Ft=new Set(["too_many_pending"]),ze=t=>t instanceof chunkLGJMFD5H_cjs.a&&t.code==="too_many_payments",Xe=t=>t instanceof chunkLGJMFD5H_cjs.a&&t.code===Te;function Ze(t){if(!(t instanceof chunkLGJMFD5H_cjs.a)||t.code&&Ft.has(t.code))return true;let{status:s}=t;return s===void 0||s===408||s===429||s>=500}var Q=t=>t.startsWith("0x")||t.startsWith("0X")?t.toLowerCase():t;function et(t){return t.rejectedPayments?t.rejectedPayments.map(({txKey:s,original:c,userOpHash:y,reason:S,final:v,movedMoney:b,rechecked:q,held:g,otherInvoice:C})=>({keys:[s,c,y].filter(L=>!!L).map(Q),reason:S,final:v,movedMoney:b===true||Kt.has(S),rechecked:q===true,held:g===true,...typeof C=="string"?{otherInvoice:C}:{}})):t.rejectedTxKeys?.map(s=>({keys:[Q(s)],final:true}))??null}var jt=(t,s)=>t!==null&&!(Date.parse(t.expiresAt??"")<=s),Qt=new Set([...st,"underpaid"]),Gt=new Set(["quoting","awaitingPayment","submitting","confirming","unconfirmed"]);function j(t){switch(t){case "processing":return "confirming";case "paid":case "partially_refunded":return "paid";case "refunded":case "underpaid":case "held":case "expired":return t;case "cancelled":return "cancelled";default:return "selectMethod"}}function tt(t,s){if(t.invoice.status!=="open")return j(t.invoice.status);if(t.buyer.required)return "buyer";let c=t.quote?.expiresAt?Date.parse(t.quote.expiresAt):Number.NaN;return t.quote&&!(c<=s)?"awaitingPayment":"selectMethod"}var nt={payer_blocked:"blocked",payer_not_expected:"blocked",buyer_required:"buyer",invoice_expired:"expired",invoice_processing:"confirming",payment_on_its_way:"confirming",payer_mismatch:"underpaid",rest_method_mismatch:"underpaid",too_many_payments:"selectMethod"},Bt=new Set(["invoice_expired","invoice_processing","payment_on_its_way"]);function Y(t){let s=t.reason?{reason:t.reason}:{};if(t.reason===Me)return $t(t.rechecked);if(t.reason===de)return t.otherInvoice?le():ct(t.keys?.[0]);if(t.reason===Ut)return {code:"payment_mismatch",message:"This payment was sent or charged under an earlier price of this invoice, so it does not pay it. The merchant holds it to return it to the wallet that sent it, and the invoice can still be paid.",...s,held:true};if(t.reason==="too_many_parts")return {code:"payment_mismatch",message:"This invoice has taken as many parts as it can, so this transfer does not pay it. The merchant holds it to return it to the wallet that sent it; send the whole rest at once.",...s,held:true};if(t.reason&&Lt.has(t.reason))return {code:"payment_mismatch",message:t.held?"This transaction came from a wallet that did not confirm this invoice, so it does not pay it. The merchant returns it to the wallet that sent it, and the invoice can still be paid from the wallet that confirmed it.":"This transaction came from a wallet that did not confirm this invoice, so it does not pay it. If money left your wallet, contact the merchant.",...s,...t.held?{held:true}:{}};let c=t.otherInvoice?{otherInvoice:t.otherInvoice}:{};return t.held?{code:"payment_mismatch",message:"This transaction is tied to another invoice, which holds it for a refund to the wallet that sent it. It does not count for this invoice. If it was your payment for this invoice, contact the merchant.",...s,held:true,...c}:t.movedMoney?{...c,code:"payment_mismatch",message:"This transaction does not pay the invoice. If money left your wallet, contact the merchant.",...s}:t.final?{code:"payment_failed",message:"The payment did not go through. Try again.",...s}:le(t.reason,t.rechecked)}function le(t,s=false){return {code:"payment_unconfirmed",message:s?"The payment is not confirmed yet; Quasar checks it again for up to 24 hours. Check your wallet before paying again.":t?"The payment could not be confirmed. If it left your wallet, contact the merchant with the transaction hash.":"The payment could not be confirmed. Check your wallet before paying again.",...t?{reason:t}:{},...s?{rechecked:true}:{}}}var Vt=()=>({code:"payment_unconfirmed",message:"The payment has not reached Quasar yet; this page keeps handing it over. Check your wallet before paying again.",reason:"submit_retrying"}),Yt=()=>({code:"payment_unconfirmed",message:"This invoice takes no more payments, and Quasar does not follow this one. If it left your wallet, contact the merchant with the transaction hash.",reason:at}),we=()=>({code:"payment_unconfirmed",message:"Quasar did not receive the payment. If it left your wallet, contact the merchant with the transaction hash.",reason:"submit_failed"}),$t=(t=false)=>({code:"payment_unconfirmed",message:t?"The payment reached the network, but Quasar has not recorded it yet; it tries again daily for up to 30 days. Do not pay again; contact the merchant with the transaction hash.":"The payment reached the network, but Quasar could not record it. Do not pay again; contact the merchant with the transaction hash.",reason:Me,...t?{rechecked:true}:{}}),ct=t=>({code:"payment_unconfirmed",...t?{txKey:t}:{},message:"The wallet used the number of this transaction for another one, which Quasar could not find, so money may have left the wallet. Do not pay again yet: name that transaction, or contact the merchant.",reason:de}),Jt=()=>({code:"payment_unconfirmed",message:"This transaction was handed over for another invoice first. Quasar credits it to the invoice that the wallet which sent it confirmed, and this page shows the result. Do not pay again meanwhile.",status:409,reason:Te}),zt=t=>t?.code==="payment_unconfirmed"&&(t.reason===Te||t.reason===Me||t.reason===de||t.reason===at),rt=t=>t.find(s=>s.reason===de&&!s.otherInvoice)??null,Xt=t=>t?.code==="payment_unconfirmed"&&t.reason===Te,te=t=>(t.unresolvedPayments??0)>0,Zt=(t,s)=>!t.final&&!t.movedMoney&&!t.rechecked&&it.has(t.reason??"")&&s.unresolvedPayments===0,ot=t=>(t.unresolvedPayments??t.pendingPayments??0)>0,qe=t=>({status:t.invoice.status,ledgerSeq:0,txHash:null,amountPaid:t.invoice.amountPaid,quoteExpiresAt:t.quote?.expiresAt??null,pendingPayments:t.invoice.pendingPayments,rejectedTxKeys:t.invoice.rejectedTxKeys,rejectedPayments:t.invoice.rejectedPayments,paymentCountsUntil:t.invoice.paymentCountsUntil,unresolvedPayments:t.invoice.unresolvedPayments,onTimeTxKeys:t.invoice.onTimeTxKeys});function ce(t){if(t instanceof chunkLGJMFD5H_cjs.a){let{reason:s,originWallet:c}=t.details??{};return {code:t.code??"request_failed",message:t.message,status:t.status,issues:t.issues,...typeof s=="string"?{reason:s}:{},...typeof c=="string"?{originWallet:c}:{}}}return {code:"request_failed",message:t instanceof Error?t.message:String(t)}}function Sn(t){let s=t.api??Ge(t.token,t.baseUrl??chunk2LAAWGEK_cjs.a),c=t.pollMs??5e3,y=t.EventSource===void 0?globalThis.EventSource??null:t.EventSource,S=null,v=null,b=null,q=null,g=false,C=null,L=c,l=false,m=[],P=false,T=[],E=null,O=new Set,U=0,Ee=0,H=null,G=null,Re=false,W=new Map,fe=false,x=null,ne=()=>({error:x?Y(x):ct()}),Ce=0,he=null,me=[],Le=new Set,re=t.handOverStorage!==void 0?t.handOverStorage:t.api?null:_e(),xe=`${Mt}${t.token}`,be=()=>{try{let _=JSON.parse(re?.getItem(xe)??"[]");return Array.isArray(_)?_.filter(o=>typeof o=="object"&&o!==null&&typeof o.txKey=="string"&&typeof o.at=="number"):[]}catch{return []}},Ue=_=>{try{_.length>0?re?.setItem(xe,JSON.stringify(_)):re?.removeItem(xe);}catch{}},lt=_=>{if(!re)return;let o=be(),a=o.find(({txKey:A})=>A===_.txKey);Ue([...o.filter(({txKey:A})=>A!==_.txKey),{txKey:_.txKey,..._.from?{from:_.from}:{},..._.connectorType?{connectorType:_.connectorType}:{},..._.methodId?{methodId:_.methodId}:{},at:a?.at??Date.now()}]);},F=_=>{if(!re)return;let o=be();o.some(({txKey:a})=>a===_)&&Ue(o.filter(({txKey:a})=>a!==_));},De=({quote:_,checkout:o})=>[...o?.payerProofs??[],...me,..._?.payerProof?.proven===true&&_.payer!==null?[{payer:_.payer,chainId:ve(_.payer)?.chainId??"",kind:_.payerProof.kind??void 0}]:[]],dt=_=>{let o=_.checkout?.methods.find(({id:M})=>M===_.methodId)?.chainId,a=o?.split(":")[0];if(!o)return [];let A=new Map;for(let M of De(_)){let D=ve(M.payer);!D||D.namespace!==a||(M.kind&&ut.has(M.kind)||M.chainId===o)&&(A.has(D.address)||A.set(D.address,M.payer));}return [...A.values()]},Ne=_=>{let{payer:o}=_,a=_.checkout?.methods.find(({id:D})=>D===_.methodId),M=o!==null&&Le.has(o)?"before_quote":a?.payerProof??"none";return M==="none"||!a?"not_needed":o&&Ht(De(_),o)?"confirmed":o!==null&&o===he&&M==="before_quote"?"confirming":M==="before_quote"?"required":"unless_relayed"};return vanilla.createStore()((_,o)=>{let a=e=>{let r={...o(),...e};_({...e,receiptUrl:r.phase==="paid"||r.phase==="refunded"?s.url("receipt"):null,paymasterUrl:r.quote?.gasless?.paymaster?s.url("paymaster"):null,logoUrl:r.checkout?.merchant.logo?s.url("logo"):null,payerProof:Ne(r),confirmedWallets:dt(r)});},A=(e,r)=>{let n=ce(e),u=o().invoiceStatus;if(u&&(ee.has(u)||N.has(u))){a({error:n,...At.has(o().phase)?{phase:j(u)}:{}});return}a({error:n,phase:nt[n.code]??r});},M=()=>{G&&clearTimeout(G),G=null,H=null,Re=false,o().followingUntil!==null&&a({followingUntil:null});},D=()=>{S?.close(),S=null,v&&clearInterval(v),v=null,b&&clearTimeout(b),b=null,q&&clearTimeout(q),q=null,M();},oe=()=>(m=[],P=false,{paymentOnTheWay:false}),Oe=()=>{P=true,U=Date.now(),O=new Set(T);},ft=(e,r)=>{if(!r)return null;let n=r.find(({keys:u})=>u.some(i=>m.includes(i)));return n||(e.pendingPayments!==0?null:r.find(({keys:u})=>u.some(i=>!O.has(i)))??null)},pe=e=>e==="underpaid"?{phase:"underpaid"}:e&&!V.has(e)?{phase:j(e)}:jt(o().quote,Date.now())?{phase:"awaitingPayment"}:{phase:"selectMethod",quote:null},ht=()=>s.view().then(e=>{if(l)return;let r=e.invoice.status==="underpaid"&&e.quote;a({checkout:e,...r?{quote:r,methodId:r.methodId}:{}});}).catch(()=>{}),He=()=>{let{invoiceStatus:e,paymentOnTheWay:r}=o();return !st.has(e??"")||N.has(e??"")&&(r||P)},mt=e=>{let r=o().paymentOnTheWay||P;D(),a(r?{...oe(),error:we(),phase:"unconfirmed"}:{error:ce(e),phase:"error"});},se=()=>{if(v||l)return;L=H!==null||g&&!o().paymentOnTheWay&&!P?Math.max(c,Be):c;let r=false,n=setInterval(()=>{if(r)return;r=true;let u=Ee;s.view().then(i=>{if(l||v!==n)return;let p=i.invoice.status==="underpaid"&&i.quote;a({checkout:i,...p?{quote:p,methodId:p.methodId}:{}}),ye(qe(i),i,u===Ee),We(i.quote);}).catch(i=>{v===n&&i instanceof chunkLGJMFD5H_cjs.a&&i.code==="checkout_not_found"&&mt(i);}).finally(()=>{r=false;});},L);v=n;},We=e=>{let{phase:r,quote:n}=o();r!=="awaitingPayment"||!n||!e||Ve(e.expiresAt,n.expiresAt)||(e.payer===n.payer&&e.methodId===n.methodId?a({quote:e}):a({quote:null,phase:"selectMethod"}));},Ie=(e,r=false)=>{let n=Date.parse(o().checkout?.invoice.dueAt??""),u=e==="cancelled"?Math.max(Date.now(),U)+Ct:Number.isFinite(n)?Math.max(Math.min(n,Date.now()),U)+Rt:Date.now()+xt;(H===null||r&&u>H)&&(H=u,G&&clearTimeout(G),G=setTimeout(()=>{G=null,!l&&(a({...oe(),invoicePaymentOnTheWay:false,...o().invoicePaymentUnresolved&&!o().error?{error:le(void 0,fe)}:{}}),D());},Math.max(0,H-Date.now())),a({followingUntil:new Date(H).toISOString()})),v&&L<Be&&(clearInterval(v),v=null,se());},ye=(e,r,n=true)=>{if(l)return;let{invoiceStatus:u,phase:i,checkout:p,paymentOnTheWay:f}=o(),w=Xt(o().error),h=et(e),k=new Set(T);h&&(T=h.flatMap(({keys:I})=>I));let d={invoiceStatus:e.status,txHash:e.txHash??o().txHash};if(n&&e.pendingPayments!==void 0&&(d.invoicePaymentOnTheWay=e.pendingPayments>0),n&&e.paymentCountsUntil!==void 0&&(d.paymentCountsUntil=e.paymentCountsUntil),n&&(e.unresolvedPayments!==void 0||e.pendingPayments!==void 0)&&(d.invoicePaymentUnresolved=ot(e)),n&&e.unresolvedPayments!==void 0&&(fe=te(e)),n&&e.onTimeTxKeys&&m.length>0&&o().paymentSentInTime!==true){let I=new Set(e.onTimeTxKeys.map(Q));d.paymentSentInTime=m.some(z=>I.has(z));}!r&&p&&e.amountPaid!==void 0&&e.amountPaid!==p.invoice.amountPaid&&(d.checkout={...p,invoice:{...p.invoice,amountPaid:e.amountPaid}});let B=f||P,ae=e.pendingPayments??0,ie=e.amountPaid!==void 0&&e.amountPaid!==null&&e.amountPaid!==E;ie&&(E=e.amountPaid);let J=u==="underpaid"&&e.status==="underpaid"&&!ie,R=null;B&&n&&Ke.has(e.status)&&(R=ft(e,h),!R&&(e.status==="open"||J)&&e.pendingPayments===0&&e.rejectedPayments&&(P||Date.now()-U>=Et)&&!(w&&(e.unresolvedPayments??0)>0)&&(R={final:false,rechecked:te(e)})),!R&&e.status==="open"&&u==="processing"&&ae===0&&(R=e.rejectedPayments?h?.find(({keys:I})=>I.some(z=>!k.has(z)))??{final:false,rechecked:te(e)}:{final:true});let Se=x;if(h&&(x=rt(h)),R&&x&&(R=x),R?.final)Object.assign(d,oe(),{error:Y(R)},e.status==="open"||e.status==="processing"||e.status==="underpaid"?pe(e.status):{phase:j(e.status)});else if(R)Object.assign(d,oe(),{error:Y(R),phase:V.has(e.status)?"unconfirmed":j(e.status)});else if(e.status==="open")i==="loading"&&(d.phase="selectMethod");else if(!J||!Gt.has(i)||i==="awaitingPayment"&&r?.invoice.restPayable===false){d.phase=j(e.status);let I=o().error;e.status==="underpaid"&&u!=="underpaid"&&I&&I.code!=="payment_mismatch"&&!x&&(d.error=null);}if(B&&!R){let I=n&&e.pendingPayments===0,z=ee.has(e.status)||e.status==="underpaid"&&!J||N.has(e.status)&&r!==void 0&&I;z&&Object.assign(d,oe()),z&&N.has(e.status)&&(d.invoicePaymentUnresolved??o().invoicePaymentUnresolved)&&(d.error=le(void 0,fe));}if(n&&ae>0&&Ke.has(e.status)){!P&&!(d.paymentOnTheWay??f)&&Oe();let I=w&&d.error===void 0;V.has(e.status)&&Pe.has(d.phase??i)&&!I&&(d.phase="confirming");}w&&d.error===void 0&&(e.status==="processing"||e.status==="underpaid"&&!J||ee.has(e.status))&&(d.error=null),x&&V.has(e.status)&&Pe.has(d.phase??i)?Object.assign(d,ne(),{phase:"unconfirmed"}):Se&&!x&&o().error?.reason===de&&!d.error&&Object.assign(d,{error:null},V.has(e.status)?pe(e.status):{}),a(d),He()?N.has(e.status)&&(Re=(e.pendingPayments??0)>0,Ie(e.status),S&&e.pendingPayments===0&&(S.close(),S=null,se())):D(),!r&&e.status!==u&&Qt.has(e.status)&&ht();let ue=o().quote;!r&&o().phase==="awaitingPayment"&&ue&&e.quoteExpiresAt&&e.quoteExpiresAt!==C&&!Ve(e.quoteExpiresAt,ue.expiresAt)&&(C=e.quoteExpiresAt,s.view().then(I=>{l||We(I.quote);}).catch(()=>{}));},ge=()=>{if(l||S||v||!He())return;if(!y)return se();let e=new y(s.url("events"));S=e;let r=()=>{b&&clearTimeout(b),b=setTimeout(()=>{b=null,!(S!==e||l)&&(e.close(),S=null,s.view().then(n=>{l||ye(qe(n),n);}).catch(()=>{}),ge());},Ot);};r(),e.addEventListener("ping",r),e.addEventListener("status",n=>{r();try{ye(JSON.parse(n.data));}catch{}}),e.onerror=()=>{if(S!==e)return;let{invoiceStatus:n,paymentOnTheWay:u}=o(),i=u||P,p=e.readyState===2;(p||N.has(n??"")&&i&&!Re)&&(e.close(),S=null,b&&clearTimeout(b),b=null,g=p,se(),p&&!q&&(q=setTimeout(()=>{q=null,!(l||!v||H!==null)&&(clearInterval(v),v=null,g=false,ge());},bt)));};},$=(e,r,n,u=false)=>{if(ee.has(n??"")||ee.has(o().invoiceStatus??"")){let{error:f,txKey:w}=o();f?.reason?.startsWith("submit_")&&w&&e.includes(w)&&a({error:null}),s.view().then(h=>{l||ye(qe(h),h);}).catch(()=>{});return}Ee+=1,U=Date.now(),P=false,m=[...m,...e.filter(f=>!!f).map(Q)],O=new Set(T.map(Q));let{invoiceStatus:i}=o(),p=i&&N.has(i)?i:null;a({txKey:r,paymentOnTheWay:true,paymentSentInTime:null,error:u?Jt():null,phase:p?j(p):u?"unconfirmed":"confirming"}),p&&Ie(p,true),v&&g&&H===null&&L>c&&(clearInterval(v),v=null,se()),ge();},Fe=async(e,r)=>{let n={txKey:e.txKey,...e.from?{from:e.from}:{},...e.connectorType?{connectorType:e.connectorType}:{},...e.methodId?{methodId:e.methodId}:{}};lt(n);let u=()=>ee.has(o().invoiceStatus??""),i=()=>N.has(o().invoiceStatus??""),p=h=>{u()||a({txKey:h,error:Yt(),...i()?{}:{phase:"unconfirmed"}}),f(0);},f=h=>{let k=qt[h];if(k===void 0||l)return;let d=setTimeout(()=>{W.delete(n.txKey),!l&&s.submit(n).then(B=>{l||(F(n.txKey),$([n.txKey],n.txKey,B?.status));},()=>f(h+1));},k);W.set(n.txKey,d);},w=r==="unconfirmed";!u()&&!i()&&!w&&a({phase:"submitting",error:null}),clearTimeout(W.get(n.txKey)),W.delete(n.txKey);try{let h=await s.submit(n);return F(n.txKey),$([n.txKey],n.txKey,h?.status),!0}catch(h){if(Xe(h))return F(n.txKey),$([n.txKey],n.txKey,void 0,true),false;if(ze(h))return p(n.txKey),false;if(h instanceof chunkLGJMFD5H_cjs.a&&Ye.has(h.code??""))return u()||a({txKey:n.txKey,error:we(),...i()?{}:{phase:"unconfirmed"}}),false;if(!Ze(h))return F(n.txKey),w&&!x||(x&&!u()?a({...ne(),...i()?{}:{phase:"unconfirmed"}}):u()||A(h,r==="submitting"?"awaitingPayment":r)),false;u()||a({txKey:n.txKey,...x?ne():{error:Vt()},...i()?{}:{phase:"unconfirmed"}});let k=Date.now()+Wt,d=()=>(o().error?.reason==="submit_retrying"||!!x)&&o().txKey===n.txKey,B=ae=>{let ie=Je[Math.min(ae,Je.length-1)];if(l)return;if(Date.now()+ie>k){d()&&a(x?ne():{error:we()});return}let J=setTimeout(()=>{W.delete(n.txKey),!l&&s.submit(n).then(R=>{l||(F(n.txKey),$([n.txKey],n.txKey,R?.status));}).catch(R=>{if(l)return;if(Ze(R))return B(ae+1);if(R instanceof chunkLGJMFD5H_cjs.a&&Ye.has(R.code??"")){d()&&a({error:we()});return}if(ze(R)){d()?p(n.txKey):F(n.txKey);return}if(F(n.txKey),Xe(R)){d()&&$([n.txKey],n.txKey,void 0,true);return}if(!d())return;if(x){a(ne());return}let Se=ce(R),ue=nt[Se.code],I=o().phase;a({error:Se,...ue?{phase:ue}:I==="unconfirmed"?pe(o().invoiceStatus):{}});});},ie);W.set(n.txKey,J);};return B(0),false}},pt=e=>{let r=be();if(r.length===0)return;let n=new Set([...e.invoice.rejectedTxKeys??[],...e.invoice.onTimeTxKeys??[]].map(Q)),u=r.filter(({txKey:i})=>!n.has(Q(i))).sort((i,p)=>i.at-p.at);for(let{txKey:i}of r)n.has(Q(i))&&F(i);(async()=>{for(let i of u){if(l)return;await Fe(i,o().phase);}})();};return {phase:"loading",checkout:null,invoiceStatus:null,methodId:null,payer:null,consentGiven:false,payerProof:"not_needed",confirmedWallets:[],quote:null,locale:null,txKey:null,paymentOnTheWay:false,invoicePaymentOnTheWay:false,paymentCountsUntil:null,invoicePaymentUnresolved:false,paymentSentInTime:null,followingUntil:null,txHash:null,error:null,receiptUrl:null,clockSkewMs:0,paymasterUrl:null,logoUrl:null,load:async()=>{a({phase:"loading",error:null});try{let e=await s.view(),{invoice:r}=e,n=et(r);n&&(T=n.flatMap(({keys:k})=>k)),E=r.amountPaid;let u=tt(e,Date.now()),i=null,p=(r.pendingPayments??0)>0&&Ke.has(r.status);p&&!o().paymentOnTheWay&&Oe(),p&&V.has(r.status)&&Pe.has(u)&&(u="confirming");let f=n?.[0],w=ot(r),h=r.status==="open"||r.status==="underpaid"||N.has(r.status);if(n&&(x=rt(n)),!p&&!o().paymentOnTheWay&&h){let k=!1;x?(i=Y(x),k=!0):f&&!f.final&&!Zt(f,r)?(i=Y(f),it.has(f.reason??"")&&!f.rechecked&&te(r)&&(i={...i,stillRead:!0}),k=!0):f?.reason==="unresolved_after_24h"?(i=Y(f),k=!0):w?(i=le(void 0,te(r)),k=!0):f?.movedMoney&&(i=Y(f)),k&&Pe.has(u)&&(u="unconfirmed");}r.unresolvedPayments!==void 0&&(fe=te(r)),a({checkout:e,invoiceStatus:r.status,locale:r.locale,quote:e.quote,methodId:e.quote?.methodId??o().methodId,payer:e.quote?.payer??o().payer,invoicePaymentOnTheWay:(r.pendingPayments??0)>0,invoicePaymentUnresolved:w,paymentCountsUntil:r.paymentCountsUntil??null,phase:u,error:i}),P&&N.has(r.status)&&Ie(r.status),ge(),pt(e);}catch(e){a({phase:"error",error:ce(e)});}},selectMethod:(e,r)=>{let{quote:n,phase:u,error:i}=o(),p=n&&n.methodId!==e;a({methodId:e,error:r?.keepError?i:null,...p?{quote:null,phase:u==="awaitingPayment"?"selectMethod":u}:{}});},setPayer:e=>{let{quote:r,phase:n,invoiceStatus:u,checkout:i,error:p}=o(),f=r&&r.payer!==e,w=e!==o().payer&&Nt(p)?{error:null}:{},h=(u??i?.invoice.status)==="underpaid",k=n==="blocked"&&e!==null&&e!==o().payer?{phase:h?"underpaid":"selectMethod",quote:h?r:null}:{};if(f&&h){a({payer:e,...w,phase:n==="awaitingPayment"?"underpaid":n,...k});return}a({payer:e,...w,...f?{quote:null,phase:n==="awaitingPayment"?"selectMethod":n}:{},...k});},clearError:()=>a({error:null}),setConsentGiven:e=>a({consentGiven:e,error:null}),releaseQuote:()=>{let{phase:e,invoiceStatus:r,checkout:n}=o();e==="awaitingPayment"&&((r??n?.invoice.status)==="underpaid"?a({error:null,phase:"underpaid"}):a({quote:null,error:null,phase:"selectMethod"}));},requestQuote:async()=>{let{methodId:e,payer:r,phase:n,checkout:u,consentGiven:i,invoiceStatus:p}=o();if(!e)return a({error:{code:"method_required",message:"Choose a payment method first"}}),null;let f=(p??u?.invoice.status)==="underpaid";if(u?.consent?.required&&!i&&!f)return a({error:{code:"consent_required",message:"Tick the consent of the checkout first"}}),null;if(o().payerProof==="required"||o().payerProof==="confirming")return a({error:{code:"payer_proof_required",message:"Confirm the paying wallet with a free signature first"}}),null;a({phase:"quoting",error:null});let w=()=>{let k=o().invoiceStatus;return k!==null&&!V.has(k)},h=()=>{let k=o().invoiceStatus;return k&&a({phase:j(k),error:null}),null};try{let k=await s.quote({methodId:e,...r?{payer:r}:{},...u?.consent&&i&&!f?{consentGiven:!0}:{}});if(w())return h();if(o().payer!==r||o().methodId!==e)return a({phase:f?"underpaid":"selectMethod"}),null;let d=Date.now()-Date.parse(k.lockedAt??"");return a({quote:k,phase:o().invoicePaymentOnTheWay?"confirming":"awaitingPayment",clockSkewMs:Number.isFinite(d)&&Math.abs(d)>It?d:0}),k}catch(k){if(k instanceof chunkLGJMFD5H_cjs.a&&k.code==="payer_proof_required"&&r&&Le.add(r),w())return h();let d=ce(k);return d.code==="payment_on_its_way"&&Oe(),f&&!Bt.has(d.code)?a({error:d,phase:"underpaid"}):A(k,n==="quoting"?"selectMethod":n),null}},confirmPayer:async e=>{let{payer:r}=o();if(!r)return a({error:{code:"payer_required",message:"Connect the paying wallet first"}}),false;if(o().payerProof==="confirmed"||o().payerProof==="not_needed")return a({error:null}),true;let{payerProofMessage:n,payerProof:u}=s;if(!n||!u)return a({error:{code:"request_failed",message:"The checkout calls cannot confirm a wallet (payerProofMessage)"}}),false;let i=++Ce;he=r,a({error:null});let p=(f,w)=>{f&&me.push(f);let h=i===Ce;h&&(he=null),!l&&(w===void 0||!h||o().payer!==r||Ne(o())==="confirmed"?a({}):w instanceof Error&&w.name==="PayerProofDeclined"?a({error:{code:"payer_proof_declined",message:$e}}):A(w,o().phase));};try{let f=await n({payer:r});if(f.proven)return p({payer:f.payer,chainId:f.chainId}),!0;let w;try{w=await e(f.message,f);}catch(k){let d=new Error(k instanceof Error?k.message:String(k));throw d.name="PayerProofDeclined",d}let h=await u({payer:r,message:f.message,signature:w});return p(h),!0}catch(f){return p(null,f),false}},abandonConfirmation:()=>{Ce++,he=null,a({});},setBuyer:async(e,r={})=>{a({error:null});try{let n=await s.buyer({buyer:e,...r.company?{company:!0}:{}});return a({checkout:n,phase:tt(n,Date.now())}),!0}catch(n){return A(n,o().phase),false}},setLocale:async e=>{let r=o().locale;a({locale:e});try{return await s.locale(e),!0}catch{return a({locale:r}),false}},submit:e=>Fe(e,o().phase),relay:async e=>{let r=o().phase;a({phase:"submitting",error:null});try{let n=await s.relay(e);return $([n.userOpHash,n.txHash],n.txHash??null),!0}catch(n){return A(n,r==="submitting"?"awaitingPayment":r),false}},grantPermission:async(e,r)=>{a({error:null});let n=async()=>{let{autoCharge:u}=await s.permission(e),i=o().checkout;return i&&a({checkout:{...i,autoCharge:u}}),true};try{try{return await n()}catch(u){let{payerProofMessage:i,payerProof:p}=s;if(!(u instanceof chunkLGJMFD5H_cjs.a&&u.code==="payer_proof_required")||!r||!i||!p)throw u;let w=await i({payer:e.payer});if(w.proven)me.push({payer:w.payer,chainId:w.chainId});else {let h;try{h=await r(w.message,w);}catch{return a({error:{code:"payer_proof_declined",message:$e}}),!1}me.push(await p({payer:e.payer,message:w.message,signature:h}));}return await n()}}catch(u){return A(u,o().phase),false}},permissionRevoked:async()=>{try{let{autoCharge:e}=await s.permissionRevoked(),r=o().checkout;return r&&a({checkout:{...r,autoCharge:e}}),e?.status!=="active"}catch{return null}},payAgain:()=>{o().phase!=="unconfirmed"||zt(o().error)||x||a({error:null,...pe(o().invoiceStatus)});},destroy:()=>{l=true;for(let e of W.values())clearTimeout(e);W.clear(),D();}}})}exports.createCheckoutStore=Sn;exports.createRefundStore=an;exports.refundAction=sn;