@phala/pay 0.8.3 → 0.9.1
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 +20 -83
- package/dist/checkout.d.ts +4 -2
- package/dist/checkout.d.ts.map +1 -1
- package/dist/checkout.js +16 -1
- package/dist/checkout.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/shared/checkout-params.d.ts +7 -0
- package/dist/shared/checkout-params.d.ts.map +1 -0
- package/dist/shared/checkout-params.js +2 -0
- package/dist/shared/checkout-params.js.map +1 -0
- package/package.json +16 -34
- package/src/checkout.ts +19 -2
- package/src/index.ts +5 -2
- package/src/shared/checkout-params.ts +6 -0
- package/dist/react/Checkout.d.ts +0 -43
- package/dist/react/Checkout.d.ts.map +0 -1
- package/dist/react/Checkout.js +0 -195
- package/dist/react/Checkout.js.map +0 -1
- package/dist/react/DepositAddress.d.ts +0 -32
- package/dist/react/DepositAddress.d.ts.map +0 -1
- package/dist/react/DepositAddress.js +0 -131
- package/dist/react/DepositAddress.js.map +0 -1
- package/dist/react/Field.d.ts +0 -7
- package/dist/react/Field.d.ts.map +0 -1
- package/dist/react/Field.js +0 -21
- package/dist/react/Field.js.map +0 -1
- package/dist/react/Icons.d.ts +0 -17
- package/dist/react/Icons.d.ts.map +0 -1
- package/dist/react/Icons.js +0 -18
- package/dist/react/Icons.js.map +0 -1
- package/dist/react/QrCode.d.ts +0 -8
- package/dist/react/QrCode.d.ts.map +0 -1
- package/dist/react/QrCode.js +0 -20
- package/dist/react/QrCode.js.map +0 -1
- package/dist/react/appearance.d.ts +0 -5
- package/dist/react/appearance.d.ts.map +0 -1
- package/dist/react/appearance.js +0 -2
- package/dist/react/appearance.js.map +0 -1
- package/dist/react/icon-paths.d.ts +0 -13
- package/dist/react/icon-paths.d.ts.map +0 -1
- package/dist/react/icon-paths.js +0 -14
- package/dist/react/icon-paths.js.map +0 -1
- package/dist/react/index.d.ts +0 -6
- package/dist/react/index.d.ts.map +0 -1
- package/dist/react/index.js +0 -6
- package/dist/react/index.js.map +0 -1
- package/dist/react/useCheckout.d.ts +0 -9
- package/dist/react/useCheckout.d.ts.map +0 -1
- package/dist/react/useCheckout.js +0 -32
- package/dist/react/useCheckout.js.map +0 -1
- package/dist/server/addresses.d.ts +0 -78
- package/dist/server/addresses.d.ts.map +0 -1
- package/dist/server/addresses.js +0 -118
- package/dist/server/addresses.js.map +0 -1
- package/dist/server/index.d.ts +0 -12
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js +0 -12
- package/dist/server/index.js.map +0 -1
- package/dist/server/sweeps.d.ts +0 -78
- package/dist/server/sweeps.d.ts.map +0 -1
- package/dist/server/sweeps.js +0 -117
- package/dist/server/sweeps.js.map +0 -1
- package/dist/server/webhook.d.ts +0 -61
- package/dist/server/webhook.d.ts.map +0 -1
- package/dist/server/webhook.js +0 -154
- package/dist/server/webhook.js.map +0 -1
- package/src/css.d.ts +0 -1
- package/src/react/Checkout.tsx +0 -475
- package/src/react/DepositAddress.tsx +0 -240
- package/src/react/Field.tsx +0 -46
- package/src/react/Icons.tsx +0 -43
- package/src/react/QrCode.tsx +0 -39
- package/src/react/appearance.ts +0 -4
- package/src/react/icon-paths.tsx +0 -13
- package/src/react/index.ts +0 -7
- package/src/react/useCheckout.ts +0 -58
- package/src/server/addresses.ts +0 -223
- package/src/server/index.ts +0 -38
- package/src/server/sweeps.ts +0 -197
- package/src/server/webhook.ts +0 -208
- package/src/styles.css +0 -80
package/README.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# @phala/pay
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Python SDK (`phala-pay`) and fulfils from the signed `deposit.credited` webhook.
|
|
3
|
+
Framework-free browser core for Phala Pay checkout sessions, retrieval helpers, wallets, payment URIs, icons, formatting, and public types. React components are published separately as [`@phala/pay-react`](../js-react).
|
|
4
|
+
|
|
5
|
+
It is the browser half of the flow; your backend creates the quote with the Node or Python merchant SDK and fulfils from the signed `deposit.credited` webhook.
|
|
7
6
|
|
|
8
7
|
## Install
|
|
9
8
|
|
|
@@ -11,10 +10,13 @@ Python SDK (`phala-pay`) and fulfils from the signed `deposit.credited` webhook.
|
|
|
11
10
|
npm install @phala/pay viem
|
|
12
11
|
```
|
|
13
12
|
|
|
13
|
+
For React components, install `@phala/pay-react` alongside `react` and `react-dom`; this package
|
|
14
|
+
itself has no React peer dependency.
|
|
15
|
+
|
|
14
16
|
`@phala/pay` shares the service's version: pin the one equal to your operator's service version
|
|
15
17
|
([compatibility](../../docs/integration.md#compatibility)).
|
|
16
18
|
|
|
17
|
-
Peer
|
|
19
|
+
Peer dependency: `viem` 2. Browser wallets are
|
|
18
20
|
found with EIP-6963 through [mipd](https://github.com/wevm/mipd), wagmi's discovery store (with a
|
|
19
21
|
`window.ethereum` fallback for wallets that do not announce themselves). If your page already
|
|
20
22
|
connects a wallet with wagmi, RainbowKit, ConnectKit, or AppKit, pass it in instead; see
|
|
@@ -30,8 +32,8 @@ connects a wallet with wagmi, RainbowKit, ConnectKit, or AppKit, pass it in inst
|
|
|
30
32
|
|
|
31
33
|
```tsx
|
|
32
34
|
"use client";
|
|
33
|
-
import { Checkout } from "@phala/pay
|
|
34
|
-
import "@phala/pay/styles.css";
|
|
35
|
+
import { Checkout } from "@phala/pay-react";
|
|
36
|
+
import "@phala/pay-react/styles.css";
|
|
35
37
|
|
|
36
38
|
export function TopUp(props: {
|
|
37
39
|
clientSecret: string;
|
|
@@ -114,7 +116,7 @@ ConnectKit, and AppKit, that is `useWalletClient()`:
|
|
|
114
116
|
|
|
115
117
|
```tsx
|
|
116
118
|
"use client";
|
|
117
|
-
import { Checkout } from "@phala/pay
|
|
119
|
+
import { Checkout } from "@phala/pay-react";
|
|
118
120
|
import { useWalletClient } from "wagmi";
|
|
119
121
|
|
|
120
122
|
export function TopUp(props: { clientSecret: string; expectedAddress: string }) {
|
|
@@ -144,7 +146,7 @@ arrives" copy; where a network's address differs (another treasury), it shows th
|
|
|
144
146
|
Credit the customer from the `deposit.credited` webhook.
|
|
145
147
|
|
|
146
148
|
```tsx
|
|
147
|
-
import { DepositAddress } from "@phala/pay
|
|
149
|
+
import { DepositAddress } from "@phala/pay-react";
|
|
148
150
|
|
|
149
151
|
<DepositAddress
|
|
150
152
|
depositAddress={{ address, networks }}
|
|
@@ -193,7 +195,7 @@ on Sepolia and about 7 seconds on Base Sepolia"); until the view is loaded it na
|
|
|
193
195
|
Import the static stylesheet once in your application entry point:
|
|
194
196
|
|
|
195
197
|
```ts
|
|
196
|
-
import "@phala/pay/styles.css";
|
|
198
|
+
import "@phala/pay-react/styles.css";
|
|
197
199
|
```
|
|
198
200
|
|
|
199
201
|
Set these CSS custom properties in your own stylesheet, after the SDK stylesheet, using a
|
|
@@ -267,82 +269,17 @@ quote's `payment_uri`, after checking that it pays exactly `amount_atomic` to `a
|
|
|
267
269
|
holding less of the token than that sends nothing: `WalletError` with `code`
|
|
268
270
|
`insufficient_balance`.
|
|
269
271
|
|
|
270
|
-
##
|
|
271
|
-
|
|
272
|
-
`@phala/pay/server` is for your backend and takes no API key (call the API itself with a
|
|
273
|
-
restricted key, `ppay_rk_…`, from the backend only, never the browser):
|
|
272
|
+
## React components
|
|
274
273
|
|
|
275
|
-
|
|
276
|
-
import { constructEvent, flushTransactions, safeBatch, verifyQuoteAddress } from "@phala/pay/server";
|
|
277
|
-
|
|
278
|
-
// Your pins, configured on your server and never read from the service. The address is derived
|
|
279
|
-
// from your treasury, not the quote's: a mismatch throws AddressMismatchError, and in live mode a
|
|
280
|
-
// chain without a pinned treasury fails closed.
|
|
281
|
-
const pins = { account: "acct_…", factory: FACTORY, implementation: IMPLEMENTATION, treasuries: { 1: TREASURY } };
|
|
282
|
-
const expectedAddress = verifyQuoteAddress(pins, quote); // pass it to <Checkout expectedAddress>
|
|
283
|
-
|
|
284
|
-
// Standard Webhooks v1a (ed25519, WebCrypto: Node 20.3+, Deno, Bun, edge runtimes). Fails closed
|
|
285
|
-
// unless the signature verifies with a pinned key and the event is your account's in this mode.
|
|
286
|
-
// WEBHOOK_PUBLIC_KEYS: your account's keys in this mode, `whpk_…`, pinned from GET /v1/attestation.
|
|
287
|
-
const event = await constructEvent(rawBody, request.headers, WEBHOOK_PUBLIC_KEYS, {
|
|
288
|
-
expectedAccount: "acct_…",
|
|
289
|
-
expectedLivemode: false,
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// Sweeping, offline: forwarders from GET /v1/forwarders?sweepable=<token>.
|
|
293
|
-
const calls = flushTransactions(forwarders, PHA);
|
|
294
|
-
const batchFile = safeBatch(1, TREASURY_SAFE, calls); // Safe Transaction Builder JSON
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
`verifyDepositAddress(pins, address)` checks every network of a deposit address the same way.
|
|
298
|
-
`quoteAddress`, `depositAddress`, `forwarderAddress`, `quoteSalt`, and `depositAddressSalt`
|
|
299
|
-
recompute an address offline from a treasury you pass, as the Python SDK does.
|
|
300
|
-
|
|
301
|
-
## Chain and token icons
|
|
302
|
-
|
|
303
|
-
`Checkout` and `DepositAddress` include compact inline icons for Ethereum, Base, USDC, USDT,
|
|
304
|
-
PHA, and ETH. Testnets reuse their mainnet family artwork. Unknown chains
|
|
305
|
-
and assets show a neutral first-letter monogram. Symbols are case-insensitive.
|
|
306
|
-
|
|
307
|
-
```tsx
|
|
308
|
-
import { NetworkIcon, AssetIcon } from "@phala/pay/react";
|
|
309
|
-
|
|
310
|
-
<NetworkIcon chainId={8453} size={16} />; // decorative beside visible "Base" text
|
|
311
|
-
<AssetIcon asset="usdc" size={20} decorative={false} />; // accessible when used alone
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
Import `@phala/pay/styles.css` for alignment. The default
|
|
315
|
-
size is 18px. Icons use SVG width/height attributes and React elements, so they need no inline
|
|
316
|
-
styles, data URI allowance, or extra CSP directives, including with `style-src 'self'`.
|
|
317
|
-
|
|
318
|
-
Framework-free hosts can call `networkIcon(chainId)` or `assetIcon(symbol)` from `@phala/pay`
|
|
319
|
-
for decorative SVG markup. Keep the
|
|
320
|
-
name visible alongside it; when used alone, supply an accessible label on the host wrapper.
|
|
321
|
-
|
|
322
|
-
Only six branded SVGs from `@web3icons/core@4.0.57` are vendored, under the MIT license in
|
|
323
|
-
`THIRD_PARTY_NOTICES`. Regenerate both the markup and JSX modules with
|
|
324
|
-
`npx -y pnpm@12.6.0 run icons:generate`; the script packs the pinned package into a temporary
|
|
325
|
-
directory, rejects unexpected SVG tags/attributes, and cleans up. No web3icons runtime package
|
|
326
|
-
is installed.
|
|
327
|
-
|
|
328
|
-
## Development
|
|
274
|
+
Install `@phala/pay-react` for `Checkout`, `DepositAddress`, hooks, icons, and styles:
|
|
329
275
|
|
|
330
276
|
```sh
|
|
331
|
-
|
|
332
|
-
pnpm run check # typecheck, lint, unit tests, build
|
|
333
|
-
pnpm run e2e # Playwright against Anvil; needs Foundry (anvil, forge) on PATH
|
|
334
|
-
pnpm run e2e:docker # the same, with Chromium from Playwright's image (as CI runs it)
|
|
277
|
+
npm install @phala/pay-react react react-dom @phala/pay viem
|
|
335
278
|
```
|
|
336
279
|
|
|
337
|
-
|
|
338
|
-
EIP-6963 wallet backed by the node (and again through a viem `WalletClient` passed as
|
|
339
|
-
`walletClient`), then decode the QR code and exercise the manual details.
|
|
340
|
-
|
|
341
|
-
## Releases
|
|
280
|
+
Import components from `@phala/pay-react` and styles from `@phala/pay-react/styles.css`. The server client and offline helpers are in `@phala/pay-server`; see its [README](../js-server/README.md).
|
|
342
281
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
[
|
|
347
|
-
[its releases before v0.5.0](https://github.com/Phala-Network/phala-pay/blob/main/sdk/js/CHANGELOG.md),
|
|
348
|
-
versioned on their own, stay in `sdk/js`.
|
|
282
|
+
The checkout session retains its last known status and quote during temporary network/5xx outages
|
|
283
|
+
and exposes `reconnecting: true` with no permanent error. Polling resumes with bounded backoff and
|
|
284
|
+
Retry-After; a successful refresh clears the reconnecting state. Invalid-secret and address-mismatch
|
|
285
|
+
handling remains unchanged. See [planned upgrades](../../docs/integration.md#planned-upgrades-and-reconnecting).
|
package/dist/checkout.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { type ClientQuote } from "./quote.js";
|
|
|
13
13
|
* backend expects (`address_mismatch`): nothing is shown to pay.
|
|
14
14
|
*/
|
|
15
15
|
export type CheckoutStatus = "loading" | "waiting" | "seen" | "confirming" | "credited" | "rejected" | "reversed" | "expired" | "canceled" | "error";
|
|
16
|
-
export type CheckoutErrorCode = "invalid_client_secret" | "address_mismatch" | "rate_limited" | "network_error" | "invalid_response" | "api_error";
|
|
16
|
+
export type CheckoutErrorCode = "invalid_client_secret" | "address_mismatch" | "rate_limited" | "network_error" | "service_unavailable" | "invalid_response" | "api_error";
|
|
17
17
|
export interface CheckoutErrorOptions extends ErrorOptions {
|
|
18
18
|
/** The failed response's `Request-Id`, `req_…`, to quote to support. */
|
|
19
19
|
requestId?: string;
|
|
@@ -38,8 +38,10 @@ export declare function responseError(response: Response, notFound: string): Che
|
|
|
38
38
|
export declare function pollDelay(interval: number, failures: number, error: CheckoutError | null): number;
|
|
39
39
|
export interface CheckoutState {
|
|
40
40
|
status: CheckoutStatus;
|
|
41
|
+
/** The last known view is retained while polling reconnects after a temporary outage. */
|
|
42
|
+
reconnecting?: boolean;
|
|
41
43
|
quote: ClientQuote | null;
|
|
42
|
-
/**
|
|
44
|
+
/** Permanent/validation failure details; temporary outages use `reconnecting` instead. */
|
|
43
45
|
error: CheckoutError | null;
|
|
44
46
|
}
|
|
45
47
|
export interface CheckoutOptions {
|
package/dist/checkout.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../src/checkout.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6C,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,SAAS,GACT,MAAM,GACN,YAAY,GACZ,UAAU,GACV,UAAU,GACV,UAAU,GACV,SAAS,GACT,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,MAAM,iBAAiB,GACzB,uBAAuB,GACvB,kBAAkB,GAClB,cAAc,GACd,eAAe,GACf,kBAAkB,GAClB,WAAW,CAAC;AAEhB,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,aAAc,SAAQ,KAAK;IAQpC,QAAQ,CAAC,IAAI,EAAE,iBAAiB;IAPlC,SAAkB,IAAI,mBAAmB;IACzC,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;gBAG7B,IAAI,EAAE,iBAAiB,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,oBAAoB;CAMjC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../src/checkout.ts"],"names":[],"mappings":"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"}
|
package/dist/checkout.js
CHANGED
|
@@ -25,6 +25,13 @@ export function responseError(response, notFound) {
|
|
|
25
25
|
if (response.status === 404) {
|
|
26
26
|
return new CheckoutError("invalid_client_secret", notFound, requestId);
|
|
27
27
|
}
|
|
28
|
+
if (response.status >= 500) {
|
|
29
|
+
const seconds = Number(response.headers.get("retry-after"));
|
|
30
|
+
return new CheckoutError("service_unavailable", "the payment service is temporarily unavailable", {
|
|
31
|
+
...requestId,
|
|
32
|
+
...(Number.isFinite(seconds) && seconds > 0 ? { retryAfter: seconds } : {}),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
28
35
|
if (response.status === 429) {
|
|
29
36
|
const seconds = Number(response.headers.get("retry-after"));
|
|
30
37
|
return new CheckoutError("rate_limited", "too many status requests", {
|
|
@@ -113,10 +120,12 @@ export function createCheckout(options) {
|
|
|
113
120
|
let state = { status: "loading", quote: null, error: null };
|
|
114
121
|
let timer;
|
|
115
122
|
let failures = 0;
|
|
123
|
+
let lastFailure = null;
|
|
116
124
|
let destroyed = false;
|
|
117
125
|
let inFlight;
|
|
118
126
|
function setState(next) {
|
|
119
127
|
if (next.status === state.status &&
|
|
128
|
+
next.reconnecting === state.reconnecting &&
|
|
120
129
|
next.error === state.error &&
|
|
121
130
|
JSON.stringify(next.quote) === JSON.stringify(state.quote)) {
|
|
122
131
|
return;
|
|
@@ -144,6 +153,7 @@ export function createCheckout(options) {
|
|
|
144
153
|
return;
|
|
145
154
|
}
|
|
146
155
|
failures = 0;
|
|
156
|
+
lastFailure = null;
|
|
147
157
|
setState({ status: checkoutStatus(quote, now() / 1000), quote, error: null });
|
|
148
158
|
}
|
|
149
159
|
catch (cause) {
|
|
@@ -154,6 +164,7 @@ export function createCheckout(options) {
|
|
|
154
164
|
? cause
|
|
155
165
|
: new CheckoutError("network_error", "could not reach the payment service", { cause });
|
|
156
166
|
failures += 1;
|
|
167
|
+
lastFailure = error;
|
|
157
168
|
const quote = state.quote;
|
|
158
169
|
if (error.code === "address_mismatch") {
|
|
159
170
|
// Fail closed: forget the quote, so nothing about its address is shown.
|
|
@@ -162,6 +173,10 @@ export function createCheckout(options) {
|
|
|
162
173
|
else if (error.code === "invalid_client_secret") {
|
|
163
174
|
setState({ status: "error", quote, error });
|
|
164
175
|
}
|
|
176
|
+
else if (error.code === "network_error" || error.code === "service_unavailable") {
|
|
177
|
+
// Do not infer expiry or discard the payer's view while chain progress is unknown.
|
|
178
|
+
setState({ status: state.status, quote, error: null, reconnecting: true });
|
|
179
|
+
}
|
|
165
180
|
else {
|
|
166
181
|
setState({
|
|
167
182
|
status: quote === null ? state.status : checkoutStatus(quote, now() / 1000),
|
|
@@ -184,7 +199,7 @@ export function createCheckout(options) {
|
|
|
184
199
|
if (finished()) {
|
|
185
200
|
return;
|
|
186
201
|
}
|
|
187
|
-
const delay = pollDelay(interval, failures,
|
|
202
|
+
const delay = pollDelay(interval, failures, lastFailure);
|
|
188
203
|
timer = setTimeout(() => {
|
|
189
204
|
void refresh().then(schedule);
|
|
190
205
|
}, delay);
|
package/dist/checkout.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkout.js","sourceRoot":"","sources":["../src/checkout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAoB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"checkout.js","sourceRoot":"","sources":["../src/checkout.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
export { CheckoutError, checkoutStatus, createCheckout, retrieveQuote, type CheckoutErrorCode, type CheckoutErrorOptions, type CheckoutOptions, type CheckoutSession, type CheckoutState, type CheckoutStatus, type RetrieveQuoteOptions, } from "./checkout.js";
|
|
1
|
+
export { CheckoutError, checkoutStatus, pollDelay, createCheckout, retrieveQuote, type CheckoutErrorCode, type CheckoutErrorOptions, type CheckoutOptions, type CheckoutSession, type CheckoutState, type CheckoutStatus, type RetrieveQuoteOptions, } from "./checkout.js";
|
|
2
2
|
export { PhalaPay, type PhalaPayOptions } from "./client.js";
|
|
3
3
|
export { depositAddressIdFromClientSecret, parseClientDepositAddress, retrieveDepositAddress, type ClientDepositAddress, type ClientDepositAddressNetwork, type DepositAddressPayment, type RetrieveDepositAddressOptions, } from "./deposit-address.js";
|
|
4
|
-
export { knownChain, networkName, transactionUrl } from "./chains.js";
|
|
5
|
-
export { formatAmount, formatCountdown, formatTokenAmount, tokenAmount } from "./format.js";
|
|
4
|
+
export { knownChain, networkName, transactionUrl, networkIconName } from "./chains.js";
|
|
5
|
+
export { formatAmount, formatCountdown, formatMinorAmount, formatTokenAmount, formatWait, tokenAmount } from "./format.js";
|
|
6
6
|
export { depositAddressTransfer, parseTransferUri, quoteTransfer, type DepositAddressAsset, type DepositAddressDetails, type DepositAddressNetwork, type TokenTransfer, type TransferRequest, } from "./payment.js";
|
|
7
7
|
export { parseClientQuote, quoteIdFromClientSecret, type ClientQuote } from "./quote.js";
|
|
8
|
+
export { assetIconName, iconMonogram, type IconName } from "./icon-names.js";
|
|
8
9
|
export { INJECTED_WALLET_UUID, WalletError, payWithWallet, watchWallets, type EthereumProvider, type Wallet, type WalletErrorCode, type WalletInfo, } from "./wallet.js";
|
|
9
10
|
export { networkIcon, assetIcon } from "./icons.js";
|
|
11
|
+
export type { CheckoutParams } from "./shared/checkout-params.js";
|
|
10
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,cAAc,EACd,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,oBAAoB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,GACnC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,SAAS,EACT,cAAc,EACd,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,oBAAoB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,GACnC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3H,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,MAAM,EACX,KAAK,eAAe,EACpB,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export { CheckoutError, checkoutStatus, createCheckout, retrieveQuote, } from "./checkout.js";
|
|
1
|
+
export { CheckoutError, checkoutStatus, pollDelay, createCheckout, retrieveQuote, } from "./checkout.js";
|
|
2
2
|
export { PhalaPay } from "./client.js";
|
|
3
3
|
export { depositAddressIdFromClientSecret, parseClientDepositAddress, retrieveDepositAddress, } from "./deposit-address.js";
|
|
4
|
-
export { knownChain, networkName, transactionUrl } from "./chains.js";
|
|
5
|
-
export { formatAmount, formatCountdown, formatTokenAmount, tokenAmount } from "./format.js";
|
|
4
|
+
export { knownChain, networkName, transactionUrl, networkIconName } from "./chains.js";
|
|
5
|
+
export { formatAmount, formatCountdown, formatMinorAmount, formatTokenAmount, formatWait, tokenAmount } from "./format.js";
|
|
6
6
|
export { depositAddressTransfer, parseTransferUri, quoteTransfer, } from "./payment.js";
|
|
7
7
|
export { parseClientQuote, quoteIdFromClientSecret } from "./quote.js";
|
|
8
|
+
export { assetIconName, iconMonogram } from "./icon-names.js";
|
|
8
9
|
export { INJECTED_WALLET_UUID, WalletError, payWithWallet, watchWallets, } from "./wallet.js";
|
|
9
10
|
export { networkIcon, assetIcon } from "./icons.js";
|
|
10
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,cAAc,EACd,aAAa,GAQd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAwB,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,sBAAsB,GAKvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,SAAS,EACT,cAAc,EACd,aAAa,GAQd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAwB,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,sBAAsB,GAKvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3H,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GAMd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAoB,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAiB,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,YAAY,GAKb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkout-params.d.ts","sourceRoot":"","sources":["../../src/shared/checkout-params.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkout-params.js","sourceRoot":"","sources":["../../src/shared/checkout-params.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phala/pay",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Phala Pay
|
|
3
|
+
"version": "0.9.1",
|
|
4
|
+
"description": "Phala Pay framework-free browser client",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"crypto",
|
|
7
7
|
"checkout",
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
"erc20",
|
|
10
10
|
"eip-681",
|
|
11
11
|
"eip-6963",
|
|
12
|
-
"react",
|
|
13
12
|
"viem"
|
|
14
13
|
],
|
|
15
14
|
"license": "Apache-2.0",
|
|
@@ -30,16 +29,7 @@
|
|
|
30
29
|
".": {
|
|
31
30
|
"types": "./dist/index.d.ts",
|
|
32
31
|
"default": "./dist/index.js"
|
|
33
|
-
}
|
|
34
|
-
"./react": {
|
|
35
|
-
"types": "./dist/react/index.d.ts",
|
|
36
|
-
"default": "./dist/react/index.js"
|
|
37
|
-
},
|
|
38
|
-
"./server": {
|
|
39
|
-
"types": "./dist/server/index.d.ts",
|
|
40
|
-
"default": "./dist/server/index.js"
|
|
41
|
-
},
|
|
42
|
-
"./styles.css": "./src/styles.css"
|
|
32
|
+
}
|
|
43
33
|
},
|
|
44
34
|
"files": [
|
|
45
35
|
"dist",
|
|
@@ -64,43 +54,35 @@
|
|
|
64
54
|
"e2e:docker": "e2e/docker.sh",
|
|
65
55
|
"check": "pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run build && pnpm run check-generated",
|
|
66
56
|
"generate:types": "openapi-typescript ../../crates/topup/openapi.json -o src/generated/openapi.d.ts --immutable",
|
|
67
|
-
"check-generated": "bash ../scripts/check-generated-js.sh"
|
|
57
|
+
"check-generated": "bash ../scripts/check-generated-js.sh",
|
|
58
|
+
"test:fixtures": "pnpm --filter @phala/pay-server run test -- --run test/shared-fixtures.test.ts test/merchant-pins-ledger.test.ts test/merchant-transport.test.ts"
|
|
68
59
|
},
|
|
69
60
|
"dependencies": {
|
|
70
|
-
"mipd": "^0.0.7"
|
|
71
|
-
"uqr": "^0.1.3"
|
|
61
|
+
"mipd": "^0.0.7"
|
|
72
62
|
},
|
|
73
63
|
"peerDependencies": {
|
|
74
|
-
"react": "^18.2.0 || ^19.0.0",
|
|
75
64
|
"viem": "^2.21.0"
|
|
76
65
|
},
|
|
77
|
-
"peerDependenciesMeta": {
|
|
78
|
-
"react": {
|
|
79
|
-
"optional": true
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
66
|
"devDependencies": {
|
|
83
67
|
"@eslint/js": "^10.0.1",
|
|
84
68
|
"@playwright/test": "1.63.0",
|
|
85
69
|
"@testing-library/dom": "^10.4.2",
|
|
86
|
-
"@
|
|
87
|
-
"@testing-library/user-event": "^14.6.7",
|
|
88
|
-
"@types/node": "^26.6.3",
|
|
89
|
-
"@types/react": "^19.3.0",
|
|
90
|
-
"@types/react-dom": "^19.3.0",
|
|
91
|
-
"@vitejs/plugin-react": "^6.1.1",
|
|
70
|
+
"@types/node": "^26.6.4",
|
|
92
71
|
"axe-core": "^4.13.0",
|
|
93
72
|
"eslint": "^10.11.0",
|
|
94
73
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
95
74
|
"jsdom": "^30.1.1",
|
|
96
75
|
"jsqr": "^1.4.0",
|
|
97
|
-
"react": "^19.3.0",
|
|
98
|
-
"react-dom": "^19.3.0",
|
|
99
76
|
"typescript": "~6.0.3",
|
|
100
77
|
"typescript-eslint": "^8.70.1",
|
|
101
|
-
"viem": "^2.
|
|
102
|
-
"vite": "^8.3.
|
|
103
|
-
"vitest": "^5.0.
|
|
104
|
-
"openapi-typescript": "7.13.0"
|
|
78
|
+
"viem": "^2.57.2",
|
|
79
|
+
"vite": "^8.3.2",
|
|
80
|
+
"vitest": "^5.0.3",
|
|
81
|
+
"openapi-typescript": "7.13.0",
|
|
82
|
+
"@types/react": "^19.3.0",
|
|
83
|
+
"@types/react-dom": "^19.3.0",
|
|
84
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
85
|
+
"react": "^19.3.0",
|
|
86
|
+
"react-dom": "^19.3.0"
|
|
105
87
|
}
|
|
106
88
|
}
|
package/src/checkout.ts
CHANGED
|
@@ -32,6 +32,7 @@ export type CheckoutErrorCode =
|
|
|
32
32
|
| "address_mismatch"
|
|
33
33
|
| "rate_limited"
|
|
34
34
|
| "network_error"
|
|
35
|
+
| "service_unavailable"
|
|
35
36
|
| "invalid_response"
|
|
36
37
|
| "api_error";
|
|
37
38
|
|
|
@@ -70,6 +71,13 @@ export function responseError(response: Response, notFound: string): CheckoutErr
|
|
|
70
71
|
if (response.status === 404) {
|
|
71
72
|
return new CheckoutError("invalid_client_secret", notFound, requestId);
|
|
72
73
|
}
|
|
74
|
+
if (response.status >= 500) {
|
|
75
|
+
const seconds = Number(response.headers.get("retry-after"));
|
|
76
|
+
return new CheckoutError("service_unavailable", "the payment service is temporarily unavailable", {
|
|
77
|
+
...requestId,
|
|
78
|
+
...(Number.isFinite(seconds) && seconds > 0 ? { retryAfter: seconds } : {}),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
73
81
|
if (response.status === 429) {
|
|
74
82
|
const seconds = Number(response.headers.get("retry-after"));
|
|
75
83
|
return new CheckoutError("rate_limited", "too many status requests", {
|
|
@@ -92,8 +100,10 @@ export function pollDelay(interval: number, failures: number, error: CheckoutErr
|
|
|
92
100
|
|
|
93
101
|
export interface CheckoutState {
|
|
94
102
|
status: CheckoutStatus;
|
|
103
|
+
/** The last known view is retained while polling reconnects after a temporary outage. */
|
|
104
|
+
reconnecting?: boolean;
|
|
95
105
|
quote: ClientQuote | null;
|
|
96
|
-
/**
|
|
106
|
+
/** Permanent/validation failure details; temporary outages use `reconnecting` instead. */
|
|
97
107
|
error: CheckoutError | null;
|
|
98
108
|
}
|
|
99
109
|
|
|
@@ -223,12 +233,14 @@ export function createCheckout(options: CheckoutOptions): CheckoutSession {
|
|
|
223
233
|
let state: CheckoutState = { status: "loading", quote: null, error: null };
|
|
224
234
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
225
235
|
let failures = 0;
|
|
236
|
+
let lastFailure: CheckoutError | null = null;
|
|
226
237
|
let destroyed = false;
|
|
227
238
|
let inFlight: Promise<void> | undefined;
|
|
228
239
|
|
|
229
240
|
function setState(next: CheckoutState): void {
|
|
230
241
|
if (
|
|
231
242
|
next.status === state.status &&
|
|
243
|
+
next.reconnecting === state.reconnecting &&
|
|
232
244
|
next.error === state.error &&
|
|
233
245
|
JSON.stringify(next.quote) === JSON.stringify(state.quote)
|
|
234
246
|
) {
|
|
@@ -261,6 +273,7 @@ export function createCheckout(options: CheckoutOptions): CheckoutSession {
|
|
|
261
273
|
return;
|
|
262
274
|
}
|
|
263
275
|
failures = 0;
|
|
276
|
+
lastFailure = null;
|
|
264
277
|
setState({ status: checkoutStatus(quote, now() / 1000), quote, error: null });
|
|
265
278
|
} catch (cause) {
|
|
266
279
|
if (destroyed || signal.aborted) {
|
|
@@ -271,12 +284,16 @@ export function createCheckout(options: CheckoutOptions): CheckoutSession {
|
|
|
271
284
|
? cause
|
|
272
285
|
: new CheckoutError("network_error", "could not reach the payment service", { cause });
|
|
273
286
|
failures += 1;
|
|
287
|
+
lastFailure = error;
|
|
274
288
|
const quote = state.quote;
|
|
275
289
|
if (error.code === "address_mismatch") {
|
|
276
290
|
// Fail closed: forget the quote, so nothing about its address is shown.
|
|
277
291
|
setState({ status: "error", quote: null, error });
|
|
278
292
|
} else if (error.code === "invalid_client_secret") {
|
|
279
293
|
setState({ status: "error", quote, error });
|
|
294
|
+
} else if (error.code === "network_error" || error.code === "service_unavailable") {
|
|
295
|
+
// Do not infer expiry or discard the payer's view while chain progress is unknown.
|
|
296
|
+
setState({ status: state.status, quote, error: null, reconnecting: true });
|
|
280
297
|
} else {
|
|
281
298
|
setState({
|
|
282
299
|
status: quote === null ? state.status : checkoutStatus(quote, now() / 1000),
|
|
@@ -301,7 +318,7 @@ export function createCheckout(options: CheckoutOptions): CheckoutSession {
|
|
|
301
318
|
if (finished()) {
|
|
302
319
|
return;
|
|
303
320
|
}
|
|
304
|
-
const delay = pollDelay(interval, failures,
|
|
321
|
+
const delay = pollDelay(interval, failures, lastFailure);
|
|
305
322
|
timer = setTimeout(() => {
|
|
306
323
|
void refresh().then(schedule);
|
|
307
324
|
}, delay);
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export {
|
|
2
2
|
CheckoutError,
|
|
3
3
|
checkoutStatus,
|
|
4
|
+
pollDelay,
|
|
4
5
|
createCheckout,
|
|
5
6
|
retrieveQuote,
|
|
6
7
|
type CheckoutErrorCode,
|
|
@@ -21,8 +22,8 @@ export {
|
|
|
21
22
|
type DepositAddressPayment,
|
|
22
23
|
type RetrieveDepositAddressOptions,
|
|
23
24
|
} from "./deposit-address.js";
|
|
24
|
-
export { knownChain, networkName, transactionUrl } from "./chains.js";
|
|
25
|
-
export { formatAmount, formatCountdown, formatTokenAmount, tokenAmount } from "./format.js";
|
|
25
|
+
export { knownChain, networkName, transactionUrl, networkIconName } from "./chains.js";
|
|
26
|
+
export { formatAmount, formatCountdown, formatMinorAmount, formatTokenAmount, formatWait, tokenAmount } from "./format.js";
|
|
26
27
|
export {
|
|
27
28
|
depositAddressTransfer,
|
|
28
29
|
parseTransferUri,
|
|
@@ -34,6 +35,7 @@ export {
|
|
|
34
35
|
type TransferRequest,
|
|
35
36
|
} from "./payment.js";
|
|
36
37
|
export { parseClientQuote, quoteIdFromClientSecret, type ClientQuote } from "./quote.js";
|
|
38
|
+
export { assetIconName, iconMonogram, type IconName } from "./icon-names.js";
|
|
37
39
|
export {
|
|
38
40
|
INJECTED_WALLET_UUID,
|
|
39
41
|
WalletError,
|
|
@@ -45,3 +47,4 @@ export {
|
|
|
45
47
|
type WalletInfo,
|
|
46
48
|
} from "./wallet.js";
|
|
47
49
|
export { networkIcon, assetIcon } from "./icons.js";
|
|
50
|
+
export type { CheckoutParams } from "./shared/checkout-params.js";
|
package/dist/react/Checkout.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import type { WalletClient } from "viem";
|
|
2
|
-
import type { CheckoutState } from "../checkout.js";
|
|
3
|
-
import type { ClientQuote } from "../quote.js";
|
|
4
|
-
import { WalletError, type EthereumProvider } from "../wallet.js";
|
|
5
|
-
import type { Appearance } from "./appearance.js";
|
|
6
|
-
export interface CheckoutProps {
|
|
7
|
-
/** The quote's `client_secret`, from your backend's `POST /v1/quotes`. */
|
|
8
|
-
clientSecret: string;
|
|
9
|
-
/**
|
|
10
|
-
* The quote's `address` as your backend's SDK recomputed it from the pinned forwarder
|
|
11
|
-
* (`PhalaPay(forwarder=…)` in Python). Required: when the service's quote names another
|
|
12
|
-
* address, the checkout fails closed and shows nothing to pay.
|
|
13
|
-
*/
|
|
14
|
-
expectedAddress: string;
|
|
15
|
-
/** The service origin, for example `https://topup.example.com`. */
|
|
16
|
-
apiBase: string;
|
|
17
|
-
/** Called once when the payment is credited, with the quote: its `amount_credited` is what was
|
|
18
|
-
* credited, which differs from `amount` for a payment of another amount or a late one. Fulfil
|
|
19
|
-
* from the `deposit.credited` webhook, not here. */
|
|
20
|
-
onSuccess?: (quote: ClientQuote) => void;
|
|
21
|
-
/** Called once when the quote expires or is canceled without a payment. */
|
|
22
|
-
onExpire?: (quote: ClientQuote) => void;
|
|
23
|
-
/** Called whenever the checkout's status changes, like Stripe Elements' `onChange`: for example,
|
|
24
|
-
* to hide your own "new payment" control while a payment is `seen` or `confirming`. */
|
|
25
|
-
onChange?: (state: CheckoutState) => void;
|
|
26
|
-
/** Called when the wallet tab could not send the payment, with the `WalletError` and the wallet
|
|
27
|
-
* it tried (the chosen browser wallet's provider, or `walletClient`): for example on
|
|
28
|
-
* `insufficient_balance` (nothing was sent), to offer your own way to fund that wallet. The
|
|
29
|
-
* checkout shows the error's message itself. */
|
|
30
|
-
onWalletError?: (error: WalletError, wallet: WalletClient | EthereumProvider) => void;
|
|
31
|
-
appearance?: Appearance;
|
|
32
|
-
/** Milliseconds between status reads; default 3000. */
|
|
33
|
-
pollInterval?: number;
|
|
34
|
-
className?: string;
|
|
35
|
-
/** The wallet button's label; default "Pay with crypto". */
|
|
36
|
-
buttonText?: string;
|
|
37
|
-
/** Your page's connected wallet, for example wagmi's `useWalletClient().data`. When set, the
|
|
38
|
-
* wallet tab pays with it and its account instead of listing the browser's wallets. */
|
|
39
|
-
walletClient?: WalletClient | undefined;
|
|
40
|
-
}
|
|
41
|
-
/** A checkout for one quote: pay from a browser wallet, by QR code, or manually, with live status. */
|
|
42
|
-
export declare function Checkout({ clientSecret, expectedAddress, apiBase, onSuccess, onExpire, onChange, onWalletError, appearance, pollInterval, className, buttonText, walletClient, }: CheckoutProps): import("react").JSX.Element;
|
|
43
|
-
//# sourceMappingURL=Checkout.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Checkout.d.ts","sourceRoot":"","sources":["../../src/react/Checkout.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAQ,YAAY,EAAE,MAAM,MAAM,CAAC;AAC/C,OAAO,KAAK,EAAqB,aAAa,EAAkB,MAAM,gBAAgB,CAAC;AAWvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EACL,WAAW,EAGX,KAAK,gBAAgB,EAEtB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMlD,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB;;wDAEoD;IACpD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACzC,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC;2FACuF;IACvF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C;;;oDAGgD;IAChD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,gBAAgB,KAAK,IAAI,CAAC;IACtF,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;2FACuF;IACvF,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACzC;AAUD,sGAAsG;AACtG,wBAAgB,QAAQ,CAAC,EACvB,YAAY,EACZ,eAAe,EACf,OAAO,EACP,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,UAAU,EACV,YAAY,EACZ,SAAS,EACT,UAA8B,EAC9B,YAAY,GACb,EAAE,aAAa,+BA0Ef"}
|