@phala/pay 0.9.1 → 0.10.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/dist/quote.js CHANGED
@@ -16,6 +16,7 @@ export function parseClientQuote(value) {
16
16
  const v = value;
17
17
  const confirmations = v["confirmations"];
18
18
  const amountCredited = v["amount_credited"];
19
+ const cancelRequestedAt = v["cancel_requested_at"];
19
20
  if (typeof v["id"] !== "string" ||
20
21
  v["object"] !== "quote" ||
21
22
  typeof v["livemode"] !== "boolean" ||
@@ -31,6 +32,7 @@ export function parseClientQuote(value) {
31
32
  !/^0x[0-9a-fA-F]{40}$/.test(v["address"]) ||
32
33
  typeof v["payment_uri"] !== "string" ||
33
34
  !isSafeInteger(v["expires_at"]) ||
35
+ !(cancelRequestedAt === undefined || cancelRequestedAt === null || isSafeInteger(cancelRequestedAt)) ||
34
36
  !oneOf(v["payment_status"], PAYMENT_STATUSES) ||
35
37
  !(confirmations === null || isSafeInteger(confirmations)) ||
36
38
  !(amountCredited === null || isSafeInteger(amountCredited)) ||
@@ -51,6 +53,7 @@ export function parseClientQuote(value) {
51
53
  address: v["address"],
52
54
  payment_uri: v["payment_uri"],
53
55
  expires_at: v["expires_at"],
56
+ ...(cancelRequestedAt === undefined ? {} : { cancel_requested_at: cancelRequestedAt }),
54
57
  payment_status: v["payment_status"],
55
58
  confirmations,
56
59
  amount_credited: amountCredited,
package/dist/quote.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"quote.js","sourceRoot":"","sources":["../src/quote.ts"],"names":[],"mappings":"AAgDA,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,CAAU,CAAC;AAC5E,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAU,CAAC;AAErG,oFAAoF;AACpF,MAAM,UAAU,uBAAuB,CAAC,YAAoB;IAC1D,MAAM,KAAK,GAAG,mCAAmC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACrE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,MAAM,aAAa,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC;IACzC,MAAM,cAAc,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC5C,IACE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,QAAQ;QAC3B,CAAC,CAAC,QAAQ,CAAC,KAAK,OAAO;QACvB,OAAO,CAAC,CAAC,UAAU,CAAC,KAAK,SAAS;QAClC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;QACnC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC,UAAU,CAAC,KAAK,QAAQ;QACjC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ;QAC9B,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAC7B,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAC7B,OAAO,CAAC,CAAC,eAAe,CAAC,KAAK,QAAQ;QACtC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;QACjC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,QAAQ;QAChC,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACzC,OAAO,CAAC,CAAC,aAAa,CAAC,KAAK,QAAQ;QACpC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAC/B,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;QAC7C,CAAC,CAAC,aAAa,KAAK,IAAI,IAAI,aAAa,CAAC,aAAa,CAAC,CAAC;QACzD,CAAC,CAAC,cAAc,KAAK,IAAI,IAAI,aAAa,CAAC,cAAc,CAAC,CAAC;QAC3D,CAAC,aAAa,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,EAC3C,CAAC;QACD,MAAM,IAAI,SAAS,CAAC,qDAAqD,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO;QACL,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;QACX,MAAM,EAAE,OAAO;QACf,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC;QACvB,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC;QACnB,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC;QACnB,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC;QACvB,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC;QACjB,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC;QACvB,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC;QACvB,aAAa,EAAE,CAAC,CAAC,eAAe,CAAC;QACjC,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC;QACrB,WAAW,EAAE,CAAC,CAAC,aAAa,CAAC;QAC7B,UAAU,EAAE,CAAC,CAAC,YAAY,CAAC;QAC3B,cAAc,EAAE,CAAC,CAAC,gBAAgB,CAAC;QACnC,aAAa;QACb,eAAe,EAAE,cAAc;QAC/B,sBAAsB,EAAE,CAAC,CAAC,wBAAwB,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAmB,KAAc,EAAE,OAAqB;IACpE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,OAA6B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACrF,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"quote.js","sourceRoot":"","sources":["../src/quote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { Hash } from "viem";
2
+ import { type ClientQuote } from "./quote.js";
3
+ export interface SubmitTransactionOptions {
4
+ apiBase: string;
5
+ clientSecret: string;
6
+ transactionHash: Hash;
7
+ /** Required for a deposit-address secret; quotes select their stored chain. */
8
+ chainId?: number;
9
+ signal?: AbortSignal;
10
+ requestTimeout?: number;
11
+ fetch?: typeof globalThis.fetch;
12
+ }
13
+ /** Sends a best-effort detection hint. Receipt of a hint says nothing about payment status. */
14
+ export declare function submitTransaction(options: SubmitTransactionOptions): Promise<void>;
15
+ type QuoteSubmission = Omit<SubmitTransactionOptions, "transactionHash" | "chainId">;
16
+ /** Keep the checkout's origin and secret out of its public, serializable quote view. */
17
+ export declare function bindQuoteSubmission(quote: ClientQuote, options: QuoteSubmission): void;
18
+ /** Automatic wallet hints never delay or change the result of an already broadcast payment. */
19
+ export declare function submitWalletTransaction(quote: ClientQuote, transactionHash: Hash): void;
20
+ export {};
21
+ //# sourceMappingURL=transactions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactions.d.ts","sourceRoot":"","sources":["../src/transactions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAGvE,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,IAAI,CAAC;IACtB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED,+FAA+F;AAC/F,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBxF;AAED,KAAK,eAAe,GAAG,IAAI,CAAC,wBAAwB,EAAE,iBAAiB,GAAG,SAAS,CAAC,CAAC;AAGrF,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAEtF;AAED,+FAA+F;AAC/F,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,GAAG,IAAI,CAKvF"}
@@ -0,0 +1,39 @@
1
+ import { quoteIdFromClientSecret } from "./quote.js";
2
+ import { requestSignal, trimTrailingSlashes } from "./request.js";
3
+ /** Sends a best-effort detection hint. Receipt of a hint says nothing about payment status. */
4
+ export async function submitTransaction(options) {
5
+ if (!/^0x[0-9a-fA-F]{64}$/.test(options.transactionHash)) {
6
+ throw new TypeError("Invalid transaction hash");
7
+ }
8
+ const addressId = /^(da_[0-9a-f]{32})_secret_/.exec(options.clientSecret)?.[1];
9
+ const id = addressId ?? quoteIdFromClientSecret(options.clientSecret);
10
+ if (addressId !== undefined && (!Number.isSafeInteger(options.chainId) || (options.chainId ?? 0) <= 0)) {
11
+ throw new TypeError("A deposit-address hint requires chainId");
12
+ }
13
+ const resource = addressId === undefined ? "quotes" : "deposit_addresses";
14
+ const url = new URL(`${trimTrailingSlashes(options.apiBase)}/v1/${resource}/${encodeURIComponent(id)}/transactions`);
15
+ url.searchParams.set("client_secret", options.clientSecret);
16
+ const response = await (options.fetch ?? globalThis.fetch)(url, {
17
+ method: "POST",
18
+ headers: { "Content-Type": "application/json" },
19
+ body: JSON.stringify({ transaction_hash: options.transactionHash, ...(addressId === undefined ? {} : { chain_id: options.chainId }) }),
20
+ signal: requestSignal(options),
21
+ credentials: "omit",
22
+ redirect: "error",
23
+ });
24
+ if (response.status !== 202)
25
+ throw new Error("Transaction hint was not received");
26
+ }
27
+ const submissions = new WeakMap();
28
+ /** Keep the checkout's origin and secret out of its public, serializable quote view. */
29
+ export function bindQuoteSubmission(quote, options) {
30
+ submissions.set(quote, options);
31
+ }
32
+ /** Automatic wallet hints never delay or change the result of an already broadcast payment. */
33
+ export function submitWalletTransaction(quote, transactionHash) {
34
+ const options = submissions.get(quote);
35
+ if (options !== undefined) {
36
+ void submitTransaction({ ...options, transactionHash }).catch(() => undefined);
37
+ }
38
+ }
39
+ //# sourceMappingURL=transactions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactions.js","sourceRoot":"","sources":["../src/transactions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAoB,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAalE,+FAA+F;AAC/F,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAiC;IACvE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,SAAS,CAAC,0BAA0B,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,SAAS,GAAG,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,EAAE,GAAG,SAAS,IAAI,uBAAuB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACtE,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACvG,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,QAAQ,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC;IAC1E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,mBAAmB,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,QAAQ,IAAI,kBAAkB,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC;IACrH,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE;QAC9D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACtI,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC;QAC9B,WAAW,EAAE,MAAM;QACnB,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;AACpF,CAAC;AAGD,MAAM,WAAW,GAAG,IAAI,OAAO,EAAgC,CAAC;AAEhE,wFAAwF;AACxF,MAAM,UAAU,mBAAmB,CAAC,KAAkB,EAAE,OAAwB;IAC9E,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,uBAAuB,CAAC,KAAkB,EAAE,eAAqB;IAC/E,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,KAAK,iBAAiB,CAAC,EAAE,GAAG,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACjF,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"AACA,OAAO,EAQL,KAAK,IAAI,EACT,KAAK,YAAY,EAClB,MAAM,MAAM,CAAC;AAKd,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,8BAA8B;AAC9B,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,2FAA2F;AAC3F,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED,iGAAiG;AACjG,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAa9E;AA8BD,MAAM,MAAM,eAAe,GACvB,UAAU,GACV,YAAY,GACZ,aAAa,GACb,sBAAsB,GACtB,QAAQ,CAAC;AAEb,qBAAa,WAAY,SAAQ,KAAK;IAIlC,QAAQ,CAAC,IAAI,EAAE,eAAe;IAHhC,SAAkB,IAAI,iBAAiB;gBAG5B,IAAI,EAAE,eAAe,EAC9B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY;CAIzB;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,GAAG,gBAAgB,EACvC,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CAoCf"}
1
+ {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"AAEA,OAAO,EAQL,KAAK,IAAI,EACT,KAAK,YAAY,EAClB,MAAM,MAAM,CAAC;AAKd,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,8BAA8B;AAC9B,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,2FAA2F;AAC3F,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED,iGAAiG;AACjG,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAa9E;AA8BD,MAAM,MAAM,eAAe,GACvB,UAAU,GACV,YAAY,GACZ,aAAa,GACb,sBAAsB,GACtB,QAAQ,CAAC;AAEb,qBAAa,WAAY,SAAQ,KAAK;IAIlC,QAAQ,CAAC,IAAI,EAAE,eAAe;IAHhC,SAAkB,IAAI,iBAAiB;gBAG5B,IAAI,EAAE,eAAe,EAC9B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY;CAIzB;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,GAAG,gBAAgB,EACvC,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CAsCf"}
package/dist/wallet.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { submitWalletTransaction } from "./transactions.js";
1
2
  import { createStore } from "mipd";
2
3
  import { BaseError, createWalletClient, custom, erc20Abi, SwitchChainError, UserRejectedRequestError, } from "viem";
3
4
  import { readContract } from "viem/actions";
@@ -82,7 +83,7 @@ export async function payWithWallet(wallet, quote) {
82
83
  throw new WalletError("insufficient_balance", `Your wallet holds ${formatUnitsGrouped(balance, quote.decimals)} ${symbol}, less than the ` +
83
84
  `${formatTokenAmount(quote)} ${symbol} to pay. Nothing was sent.`);
84
85
  }
85
- return await client.writeContract({
86
+ const hash = await client.writeContract({
86
87
  account,
87
88
  chain: knownChain(transfer.chainId) ?? null,
88
89
  address: transfer.token,
@@ -90,6 +91,8 @@ export async function payWithWallet(wallet, quote) {
90
91
  functionName: "transfer",
91
92
  args: [transfer.to, transfer.amount],
92
93
  });
94
+ submitWalletTransaction(quote, hash);
95
+ return hash;
93
96
  }
94
97
  catch (error) {
95
98
  if (error instanceof WalletError) {
@@ -1 +1 @@
1
- {"version":3,"file":"wallet.js","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,MAAM,EACN,QAAQ,EACR,gBAAgB,EAChB,wBAAwB,GAIzB,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAsB7C,iGAAiG;AACjG,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,QAAqC;IAChE,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACb,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC;IACzB,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE;QAC/E,eAAe,EAAE,IAAI;KACtB,CAAC,CAAC;IACH,OAAO,GAAG,EAAE;QACV,WAAW,EAAE,CAAC;QACd,KAAK,CAAC,OAAO,EAAE,CAAC;IAClB,CAAC,CAAC;AACJ,CAAC;AAID,+FAA+F;AAC/F,SAAS,WAAW,CAAC,aAAsC;IACzD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,aAAa,EAAE,CAAC;QAC/C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,OAAO,IAAI,EAAE,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7F,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACnG,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,kGAAkG;IAClG,MAAM,QAAQ,GAAI,MAA0C,CAAC,QAAQ,CAAC;IACtE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YAChF,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,OAAQ,KAAsD,EAAE,OAAO,KAAK,UAAU,CAAC;AAChG,CAAC;AASD,MAAM,OAAO,WAAY,SAAQ,KAAK;IAIzB;IAHO,IAAI,GAAG,aAAa,CAAC;IAEvC,YACW,IAAqB,EAC9B,OAAe,EACf,OAAsB;QAEtB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAJf,SAAI,GAAJ,IAAI,CAAiB;IAKhC,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAuC,EACvC,KAAkB;IAElB,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACnG,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,WAAW,CAAC,YAAY,EAAE,8BAA8B,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QACxE,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACpE,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YACzC,MAAM,IAAI,WAAW,CACnB,sBAAsB,EACtB,qBAAqB,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,MAAM,kBAAkB;gBAC1F,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,MAAM,4BAA4B,CACpE,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,MAAM,CAAC,aAAa,CAAC;YAChC,OAAO;YACP,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI;YAC3C,OAAO,EAAE,QAAQ,CAAC,KAAK;YACvB,GAAG,EAAE,QAAQ;YACb,YAAY,EAAE,UAAU;YACxB,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC;SACrC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACjC,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,WAAW,CAAC,UAAU,EAAE,wCAAwC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAChG,CAAC;QACD,MAAM,IAAI,WAAW,CAAC,QAAQ,EAAE,uCAAuC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,YAAY,CAAC,MAAoB,EAAE,KAAc,EAAE,KAAc;IAC9E,IAAI,CAAC;QACH,OAAO,MAAM,YAAY,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACjH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAuC;IAC7D,OAAO,eAAe,IAAI,MAAM,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAoB,EAAE,OAAe;IAC9D,IAAI,CAAC,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC;QAC5C,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAClD,MAAM,WAAW,CAAC,KAAK,CAAC;gBACtB,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,IAAI,WAAW,CAAC,aAAa,EAAE,yBAAyB,WAAW,CAAC,OAAO,CAAC,EAAE,EAAE;oBAC9E,KAAK,EAAE,KAAK;iBACb,CAAC,CAAC;QACT,CAAC;QACD,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC;YAC5C,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IACD,IAAI,CAAC,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC;QAC5C,MAAM,IAAI,WAAW,CAAC,aAAa,EAAE,yBAAyB,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACxF,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,KAAK,YAAY,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,wBAAwB,CAAC,KAAK,IAAI,CAAC;AACzG,CAAC;AAED;kFACkF;AAClF,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,CACL,KAAK,YAAY,SAAS;QAC1B,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACf,MAAM,MAAM,GAAI,CAA8D,EAAE,IAAI,CAAC;YACrF,OAAO,CAAC,YAAY,gBAAgB,IAAI,MAAM,EAAE,aAAa,EAAE,IAAI,KAAK,gBAAgB,CAAC,IAAI,CAAC;QAChG,CAAC,CAAC,KAAK,IAAI,CACZ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"wallet.js","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phala/pay",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "Phala Pay framework-free browser client",
5
5
  "keywords": [
6
6
  "crypto",
@@ -52,10 +52,7 @@
52
52
  "test": "vitest run",
53
53
  "e2e": "playwright test",
54
54
  "e2e:docker": "e2e/docker.sh",
55
- "check": "pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run build && pnpm run check-generated",
56
- "generate:types": "openapi-typescript ../../crates/topup/openapi.json -o src/generated/openapi.d.ts --immutable",
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"
55
+ "check": "pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run build"
59
56
  },
60
57
  "dependencies": {
61
58
  "mipd": "^0.0.7"
@@ -78,7 +75,6 @@
78
75
  "viem": "^2.57.2",
79
76
  "vite": "^8.3.2",
80
77
  "vitest": "^5.0.3",
81
- "openapi-typescript": "7.13.0",
82
78
  "@types/react": "^19.3.0",
83
79
  "@types/react-dom": "^19.3.0",
84
80
  "@vitejs/plugin-react": "^6.1.1",
package/src/checkout.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { bindQuoteSubmission } from "./transactions.js";
1
2
  import { requestSignal, trimTrailingSlashes } from "./request.js";
2
3
  import { getAddress, isAddress, isAddressEqual } from "viem";
3
4
  import { parseClientQuote, quoteIdFromClientSecret, type ClientQuote } from "./quote.js";
@@ -37,6 +38,8 @@ export type CheckoutErrorCode =
37
38
  | "api_error";
38
39
 
39
40
  export interface CheckoutErrorOptions extends ErrorOptions {
41
+ /** The HTTP status, when the error came from a response. */
42
+ status?: number;
40
43
  /** The failed response's `Request-Id`, `req_…`, to quote to support. */
41
44
  requestId?: string;
42
45
  /** For `rate_limited`: the seconds the service asked to wait (`Retry-After`). */
@@ -45,6 +48,8 @@ export interface CheckoutErrorOptions extends ErrorOptions {
45
48
 
46
49
  export class CheckoutError extends Error {
47
50
  override readonly name = "CheckoutError";
51
+ /** The HTTP status, when the error came from a response. */
52
+ readonly status?: number;
48
53
  /** The failed response's `Request-Id`, when the service answered. */
49
54
  readonly requestId: string | undefined;
50
55
  /** For `rate_limited`: the seconds to wait before the next read. */
@@ -56,46 +61,60 @@ export class CheckoutError extends Error {
56
61
  options?: CheckoutErrorOptions,
57
62
  ) {
58
63
  super(message, options);
64
+ if (options?.status !== undefined) {
65
+ this.status = options.status;
66
+ }
59
67
  this.requestId = options?.requestId;
60
68
  this.retryAfter = options?.retryAfter;
61
69
  }
62
70
  }
63
71
 
64
72
  /**
65
- * The error of a failed read of a public view, with the response's `Request-Id` and, on `429`,
66
- * its `Retry-After`.
73
+ * The error of a failed read of a public view, with the response's HTTP status, `Request-Id`
74
+ * and, on `429`, its `Retry-After`.
67
75
  */
68
76
  export function responseError(response: Response, notFound: string): CheckoutError {
69
77
  const header = response.headers.get("request-id");
70
- const requestId = header === null ? {} : { requestId: header };
78
+ const options = { status: response.status, ...(header === null ? {} : { requestId: header }) };
71
79
  if (response.status === 404) {
72
- return new CheckoutError("invalid_client_secret", notFound, requestId);
80
+ return new CheckoutError("invalid_client_secret", notFound, options);
73
81
  }
74
82
  if (response.status >= 500) {
75
83
  const seconds = Number(response.headers.get("retry-after"));
76
84
  return new CheckoutError("service_unavailable", "the payment service is temporarily unavailable", {
77
- ...requestId,
85
+ ...options,
78
86
  ...(Number.isFinite(seconds) && seconds > 0 ? { retryAfter: seconds } : {}),
79
87
  });
80
88
  }
81
89
  if (response.status === 429) {
82
90
  const seconds = Number(response.headers.get("retry-after"));
83
91
  return new CheckoutError("rate_limited", "too many status requests", {
84
- ...requestId,
92
+ ...options,
85
93
  ...(Number.isFinite(seconds) && seconds > 0 ? { retryAfter: seconds } : {}),
86
94
  });
87
95
  }
88
96
  return new CheckoutError(
89
97
  "api_error",
90
98
  `the payment service answered ${response.status}`,
91
- requestId,
99
+ options,
92
100
  );
93
101
  }
94
102
 
95
- /** The delay before the next read after `failures` failed ones, at least what `error` asks. */
96
- export function pollDelay(interval: number, failures: number, error: CheckoutError | null): number {
103
+ /**
104
+ * The next read's delay with uniform ±20% jitter capped at MAX_BACKOFF after jitter.
105
+ * Retry-After remains a minimum, even when it asks for longer than the backoff cap.
106
+ * `random` defaults to Math.random and can be injected for deterministic tests.
107
+ */
108
+ export function pollDelay(
109
+ interval: number,
110
+ failures: number,
111
+ error: CheckoutError | null,
112
+ random: () => number = Math.random,
113
+ ): number {
97
114
  const backoff = failures === 0 ? interval : Math.min(interval * 2 ** failures, MAX_BACKOFF);
98
- return Math.max(backoff, (error?.retryAfter ?? 0) * 1000);
115
+ const retryAfter = (error?.retryAfter ?? 0) * 1000;
116
+ const jittered = Math.max(backoff, retryAfter) * (0.8 + 0.4 * random());
117
+ return Math.max(Math.min(jittered, MAX_BACKOFF), retryAfter);
99
118
  }
100
119
 
101
120
  export interface CheckoutState {
@@ -180,14 +199,21 @@ export async function retrieveQuote(options: RetrieveQuoteOptions): Promise<Clie
180
199
  } catch (cause) {
181
200
  throw new CheckoutError("invalid_response", "unexpected response from the payment service", {
182
201
  cause,
202
+ status: response.status,
183
203
  });
184
204
  }
185
205
  if (!isAddressEqual(getAddress(quote.address), expected)) {
186
206
  throw new CheckoutError(
187
207
  "address_mismatch",
188
208
  "the quote's address is not the one the merchant expects",
209
+ { status: response.status },
189
210
  );
190
211
  }
212
+ bindQuoteSubmission(quote, {
213
+ apiBase: options.apiBase, clientSecret: options.clientSecret,
214
+ ...(options.fetch === undefined ? {} : { fetch: options.fetch }),
215
+ ...(options.requestTimeout === undefined ? {} : { requestTimeout: options.requestTimeout }),
216
+ });
191
217
  return quote;
192
218
  }
193
219
 
@@ -229,10 +255,12 @@ export function createCheckout(options: CheckoutOptions): CheckoutSession {
229
255
  const now = options.now ?? Date.now;
230
256
  const interval = options.pollInterval ?? DEFAULT_POLL_INTERVAL;
231
257
  const listeners = new Set<(state: CheckoutState) => void>();
258
+ const visibilityDocument = typeof document === "undefined" ? undefined : document;
232
259
 
233
260
  let state: CheckoutState = { status: "loading", quote: null, error: null };
234
261
  let timer: ReturnType<typeof setTimeout> | undefined;
235
262
  let failures = 0;
263
+ let clientFailures = 0;
236
264
  let lastFailure: CheckoutError | null = null;
237
265
  let destroyed = false;
238
266
  let inFlight: Promise<void> | undefined;
@@ -273,6 +301,7 @@ export function createCheckout(options: CheckoutOptions): CheckoutSession {
273
301
  return;
274
302
  }
275
303
  failures = 0;
304
+ clientFailures = 0;
276
305
  lastFailure = null;
277
306
  setState({ status: checkoutStatus(quote, now() / 1000), quote, error: null });
278
307
  } catch (cause) {
@@ -284,6 +313,14 @@ export function createCheckout(options: CheckoutOptions): CheckoutSession {
284
313
  ? cause
285
314
  : new CheckoutError("network_error", "could not reach the payment service", { cause });
286
315
  failures += 1;
316
+ clientFailures =
317
+ error.status !== undefined &&
318
+ error.status >= 400 &&
319
+ error.status < 500 &&
320
+ error.status !== 408 &&
321
+ error.status !== 429
322
+ ? clientFailures + 1
323
+ : 0;
287
324
  lastFailure = error;
288
325
  const quote = state.quote;
289
326
  if (error.code === "address_mismatch") {
@@ -291,6 +328,8 @@ export function createCheckout(options: CheckoutOptions): CheckoutSession {
291
328
  setState({ status: "error", quote: null, error });
292
329
  } else if (error.code === "invalid_client_secret") {
293
330
  setState({ status: "error", quote, error });
331
+ } else if (clientFailures >= 3) {
332
+ setState({ status: "error", quote, error });
294
333
  } else if (error.code === "network_error" || error.code === "service_unavailable") {
295
334
  // Do not infer expiry or discard the payer's view while chain progress is unknown.
296
335
  setState({ status: state.status, quote, error: null, reconnecting: true });
@@ -315,16 +354,35 @@ export function createCheckout(options: CheckoutOptions): CheckoutSession {
315
354
  }
316
355
 
317
356
  function schedule(): void {
318
- if (finished()) {
357
+ clearTimeout(timer);
358
+ if (finished() || visibilityDocument?.visibilityState === "hidden") {
319
359
  return;
320
360
  }
321
361
  const delay = pollDelay(interval, failures, lastFailure);
322
362
  timer = setTimeout(() => {
323
- void refresh().then(schedule);
363
+ if (!finished() && visibilityDocument?.visibilityState !== "hidden") {
364
+ void refresh().then(schedule);
365
+ }
324
366
  }, delay);
325
367
  }
326
368
 
327
- void refresh().then(schedule);
369
+ function visibilityChanged(): void {
370
+ clearTimeout(timer);
371
+ if (visibilityDocument?.visibilityState !== "hidden" && !finished()) {
372
+ void refresh().then(schedule);
373
+ }
374
+ }
375
+
376
+ function stopPolling(): void {
377
+ clearTimeout(timer);
378
+ visibilityDocument?.removeEventListener("visibilitychange", visibilityChanged);
379
+ }
380
+
381
+ visibilityDocument?.addEventListener("visibilitychange", visibilityChanged);
382
+ signal.addEventListener("abort", stopPolling, { once: true });
383
+ if (visibilityDocument?.visibilityState !== "hidden") {
384
+ void refresh().then(schedule);
385
+ }
328
386
 
329
387
  return {
330
388
  getState: () => state,
@@ -338,7 +396,7 @@ export function createCheckout(options: CheckoutOptions): CheckoutSession {
338
396
  destroy() {
339
397
  destroyed = true;
340
398
  controller.abort();
341
- clearTimeout(timer);
399
+ stopPolling();
342
400
  listeners.clear();
343
401
  },
344
402
  };
package/src/client.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { Hash } from "viem";
2
+ import { submitTransaction, type SubmitTransactionOptions } from "./transactions.js";
1
3
  import {
2
4
  createCheckout,
3
5
  retrieveQuote,
@@ -60,6 +62,15 @@ export class PhalaPay {
60
62
  });
61
63
  }
62
64
 
65
+ /** Acknowledges a hint only; continue polling the object for payment status. */
66
+ submitTransaction(
67
+ clientSecret: string,
68
+ transactionHash: Hash,
69
+ options: Pick<SubmitTransactionOptions, "chainId" | "signal" | "requestTimeout"> = {},
70
+ ): Promise<void> {
71
+ return submitTransaction({ ...options, clientSecret, transactionHash, apiBase: this.apiBase, ...this.#fetchOption() });
72
+ }
73
+
63
74
  #fetchOption(): { fetch?: typeof globalThis.fetch } {
64
75
  return this.#fetch === undefined ? {} : { fetch: this.#fetch };
65
76
  }
@@ -94,6 +94,7 @@ export async function retrieveDepositAddress(
94
94
  } catch (cause) {
95
95
  throw new CheckoutError("invalid_response", "unexpected response from the payment service", {
96
96
  cause,
97
+ status: response.status,
97
98
  });
98
99
  }
99
100
  }
package/src/index.ts CHANGED
@@ -48,3 +48,5 @@ export {
48
48
  } from "./wallet.js";
49
49
  export { networkIcon, assetIcon } from "./icons.js";
50
50
  export type { CheckoutParams } from "./shared/checkout-params.js";
51
+
52
+ export { submitTransaction, type SubmitTransactionOptions } from "./transactions.js";
package/src/quote.ts CHANGED
@@ -23,6 +23,8 @@ export interface ClientQuote {
23
23
  payment_uri: string;
24
24
  /** Unix seconds; after this the address must no longer be shown. */
25
25
  expires_at: number;
26
+ /** Unix seconds of a cancellation request; the quote stays open until dual coverage closes it. */
27
+ cancel_requested_at?: number | null;
26
28
  /**
27
29
  * `seen` once in a block (a reorg can remove it), `confirming` while a payment at the route's
28
30
  * confirmation is valued and screened, `credited` once it is credited (typically
@@ -66,6 +68,7 @@ export function parseClientQuote(value: unknown): ClientQuote {
66
68
  const v = value as Record<string, unknown>;
67
69
  const confirmations = v["confirmations"];
68
70
  const amountCredited = v["amount_credited"];
71
+ const cancelRequestedAt = v["cancel_requested_at"];
69
72
  if (
70
73
  typeof v["id"] !== "string" ||
71
74
  v["object"] !== "quote" ||
@@ -82,6 +85,7 @@ export function parseClientQuote(value: unknown): ClientQuote {
82
85
  !/^0x[0-9a-fA-F]{40}$/.test(v["address"]) ||
83
86
  typeof v["payment_uri"] !== "string" ||
84
87
  !isSafeInteger(v["expires_at"]) ||
88
+ !(cancelRequestedAt === undefined || cancelRequestedAt === null || isSafeInteger(cancelRequestedAt)) ||
85
89
  !oneOf(v["payment_status"], PAYMENT_STATUSES) ||
86
90
  !(confirmations === null || isSafeInteger(confirmations)) ||
87
91
  !(amountCredited === null || isSafeInteger(amountCredited)) ||
@@ -103,6 +107,7 @@ export function parseClientQuote(value: unknown): ClientQuote {
103
107
  address: v["address"],
104
108
  payment_uri: v["payment_uri"],
105
109
  expires_at: v["expires_at"],
110
+ ...(cancelRequestedAt === undefined ? {} : { cancel_requested_at: cancelRequestedAt }),
106
111
  payment_status: v["payment_status"],
107
112
  confirmations,
108
113
  amount_credited: amountCredited,
@@ -0,0 +1,54 @@
1
+ import type { Hash } from "viem";
2
+ import { quoteIdFromClientSecret, type ClientQuote } from "./quote.js";
3
+ import { requestSignal, trimTrailingSlashes } from "./request.js";
4
+
5
+ export interface SubmitTransactionOptions {
6
+ apiBase: string;
7
+ clientSecret: string;
8
+ transactionHash: Hash;
9
+ /** Required for a deposit-address secret; quotes select their stored chain. */
10
+ chainId?: number;
11
+ signal?: AbortSignal;
12
+ requestTimeout?: number;
13
+ fetch?: typeof globalThis.fetch;
14
+ }
15
+
16
+ /** Sends a best-effort detection hint. Receipt of a hint says nothing about payment status. */
17
+ export async function submitTransaction(options: SubmitTransactionOptions): Promise<void> {
18
+ if (!/^0x[0-9a-fA-F]{64}$/.test(options.transactionHash)) {
19
+ throw new TypeError("Invalid transaction hash");
20
+ }
21
+ const addressId = /^(da_[0-9a-f]{32})_secret_/.exec(options.clientSecret)?.[1];
22
+ const id = addressId ?? quoteIdFromClientSecret(options.clientSecret);
23
+ if (addressId !== undefined && (!Number.isSafeInteger(options.chainId) || (options.chainId ?? 0) <= 0)) {
24
+ throw new TypeError("A deposit-address hint requires chainId");
25
+ }
26
+ const resource = addressId === undefined ? "quotes" : "deposit_addresses";
27
+ const url = new URL(`${trimTrailingSlashes(options.apiBase)}/v1/${resource}/${encodeURIComponent(id)}/transactions`);
28
+ url.searchParams.set("client_secret", options.clientSecret);
29
+ const response = await (options.fetch ?? globalThis.fetch)(url, {
30
+ method: "POST",
31
+ headers: { "Content-Type": "application/json" },
32
+ body: JSON.stringify({ transaction_hash: options.transactionHash, ...(addressId === undefined ? {} : { chain_id: options.chainId }) }),
33
+ signal: requestSignal(options),
34
+ credentials: "omit",
35
+ redirect: "error",
36
+ });
37
+ if (response.status !== 202) throw new Error("Transaction hint was not received");
38
+ }
39
+
40
+ type QuoteSubmission = Omit<SubmitTransactionOptions, "transactionHash" | "chainId">;
41
+ const submissions = new WeakMap<ClientQuote, QuoteSubmission>();
42
+
43
+ /** Keep the checkout's origin and secret out of its public, serializable quote view. */
44
+ export function bindQuoteSubmission(quote: ClientQuote, options: QuoteSubmission): void {
45
+ submissions.set(quote, options);
46
+ }
47
+
48
+ /** Automatic wallet hints never delay or change the result of an already broadcast payment. */
49
+ export function submitWalletTransaction(quote: ClientQuote, transactionHash: Hash): void {
50
+ const options = submissions.get(quote);
51
+ if (options !== undefined) {
52
+ void submitTransaction({ ...options, transactionHash }).catch(() => undefined);
53
+ }
54
+ }
package/src/wallet.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { submitWalletTransaction } from "./transactions.js";
1
2
  import { createStore } from "mipd";
2
3
  import {
3
4
  BaseError,
@@ -136,7 +137,7 @@ export async function payWithWallet(
136
137
  `${formatTokenAmount(quote)} ${symbol} to pay. Nothing was sent.`,
137
138
  );
138
139
  }
139
- return await client.writeContract({
140
+ const hash = await client.writeContract({
140
141
  account,
141
142
  chain: knownChain(transfer.chainId) ?? null,
142
143
  address: transfer.token,
@@ -144,6 +145,8 @@ export async function payWithWallet(
144
145
  functionName: "transfer",
145
146
  args: [transfer.to, transfer.amount],
146
147
  });
148
+ submitWalletTransaction(quote, hash);
149
+ return hash;
147
150
  } catch (error) {
148
151
  if (error instanceof WalletError) {
149
152
  throw error;