@rhinestone/1auth 0.7.6 → 0.8.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/dist/chunk-IX45E5LE.mjs +6135 -0
- package/dist/chunk-IX45E5LE.mjs.map +1 -0
- package/dist/chunk-ZDW2LY6H.mjs +116 -0
- package/dist/chunk-ZDW2LY6H.mjs.map +1 -0
- package/dist/{client-Dn6mL7BZ.d.ts → client-B0vb_deA.d.mts} +26 -14
- package/dist/{client-C8QSA1th.d.mts → client-CPt1hn4_.d.ts} +26 -14
- package/dist/errors-Blx9IVF_.d.mts +16 -0
- package/dist/errors-Cg605N0t.d.ts +16 -0
- package/dist/headless.d.mts +5 -10
- package/dist/headless.d.ts +5 -10
- package/dist/headless.js +74 -24
- package/dist/headless.js.map +1 -1
- package/dist/headless.mjs +74 -24
- package/dist/headless.mjs.map +1 -1
- package/dist/index.d.mts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +678 -220
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +68 -5271
- package/dist/index.mjs.map +1 -1
- package/dist/{provider-CJv38fIK.d.mts → provider-CNDrBzGs.d.mts} +2 -2
- package/dist/{provider-BsVmPgkQ.d.ts → provider-DwZPA2N1.d.ts} +2 -2
- package/dist/react.d.mts +3 -2
- package/dist/react.d.ts +3 -2
- package/dist/react.js +61 -1
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +6 -1
- package/dist/react.mjs.map +1 -1
- package/dist/server.d.mts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/{types-Dzm5lZK-.d.mts → types-BN6cCuAd.d.mts} +88 -69
- package/dist/{types-Dzm5lZK-.d.ts → types-BN6cCuAd.d.ts} +88 -69
- package/dist/{verify-0VXQpQBJ.d.mts → verify-CEzkfM92.d.mts} +1 -1
- package/dist/{verify-9UgxLSdo.d.ts → verify-DhEkGnym.d.ts} +1 -1
- package/dist/wagmi.d.mts +3 -3
- package/dist/wagmi.d.ts +3 -3
- package/dist/wagmi.js +116 -26
- package/dist/wagmi.js.map +1 -1
- package/dist/wagmi.mjs +3 -1
- package/dist/wagmi.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-E4YZS7FZ.mjs +0 -565
- package/dist/chunk-E4YZS7FZ.mjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Address } from 'viem';
|
|
2
|
-
import { O as OneAuthClient } from './client-
|
|
3
|
-
import { C as CloseOnStatus, h as SignerType } from './types-
|
|
2
|
+
import { O as OneAuthClient } from './client-B0vb_deA.mjs';
|
|
3
|
+
import { C as CloseOnStatus, h as SignerType } from './types-BN6cCuAd.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* EIP-1193 JSON-RPC provider factory for the 1auth passkey authentication system.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Address } from 'viem';
|
|
2
|
-
import { O as OneAuthClient } from './client-
|
|
3
|
-
import { C as CloseOnStatus, h as SignerType } from './types-
|
|
2
|
+
import { O as OneAuthClient } from './client-CPt1hn4_.js';
|
|
3
|
+
import { C as CloseOnStatus, h as SignerType } from './types-BN6cCuAd.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* EIP-1193 JSON-RPC provider factory for the 1auth passkey authentication system.
|
package/dist/react.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { O as OneAuthClient } from './client-
|
|
4
|
-
import {
|
|
3
|
+
import { O as OneAuthClient } from './client-B0vb_deA.mjs';
|
|
4
|
+
import { a2 as SendIntentOptions, j as SendIntentResult, C as CloseOnStatus, aA as SponsorshipUrlConfig, az as SponsorshipCallbackConfig } from './types-BN6cCuAd.mjs';
|
|
5
|
+
export { O as OneAuthError } from './errors-Blx9IVF_.mjs';
|
|
5
6
|
import 'viem';
|
|
6
7
|
import '@rhinestone/sdk';
|
|
7
8
|
|
package/dist/react.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { O as OneAuthClient } from './client-
|
|
4
|
-
import {
|
|
3
|
+
import { O as OneAuthClient } from './client-CPt1hn4_.js';
|
|
4
|
+
import { a2 as SendIntentOptions, j as SendIntentResult, C as CloseOnStatus, aA as SponsorshipUrlConfig, az as SponsorshipCallbackConfig } from './types-BN6cCuAd.js';
|
|
5
|
+
export { O as OneAuthError } from './errors-Cg605N0t.js';
|
|
5
6
|
import 'viem';
|
|
6
7
|
import '@rhinestone/sdk';
|
|
7
8
|
|
package/dist/react.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/react.tsx
|
|
31
31
|
var react_exports = {};
|
|
32
32
|
__export(react_exports, {
|
|
33
|
+
OneAuthError: () => OneAuthError,
|
|
33
34
|
PayButton: () => PayButton,
|
|
34
35
|
createCachedSponsorship: () => createCachedSponsorship,
|
|
35
36
|
isAccessTokenFresh: () => isAccessTokenFresh,
|
|
@@ -62,6 +63,64 @@ async function tokenFetchError(label, response) {
|
|
|
62
63
|
);
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
// src/errors.ts
|
|
67
|
+
function isPlainRecord(value) {
|
|
68
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
69
|
+
const prototype = Object.getPrototypeOf(value);
|
|
70
|
+
return prototype === Object.prototype || prototype === null;
|
|
71
|
+
}
|
|
72
|
+
function normalizeCandidateError(value) {
|
|
73
|
+
if (!isPlainRecord(value)) return void 0;
|
|
74
|
+
const candidate = {};
|
|
75
|
+
if (typeof value.code === "string") candidate.code = value.code;
|
|
76
|
+
if (typeof value.message === "string") candidate.message = value.message;
|
|
77
|
+
const details = normalizeOneAuthErrorDetails(value.details);
|
|
78
|
+
if (details) candidate.details = details;
|
|
79
|
+
return Object.keys(candidate).length > 0 ? candidate : void 0;
|
|
80
|
+
}
|
|
81
|
+
function normalizeOneAuthErrorDetails(value) {
|
|
82
|
+
if (typeof value === "string") return { reason: value };
|
|
83
|
+
if (Array.isArray(value)) {
|
|
84
|
+
const candidateErrors = value.map(normalizeCandidateError).filter((candidate) => candidate !== void 0);
|
|
85
|
+
return candidateErrors.length > 0 ? { candidateErrors } : void 0;
|
|
86
|
+
}
|
|
87
|
+
if (!isPlainRecord(value)) return void 0;
|
|
88
|
+
const details = {};
|
|
89
|
+
if (typeof value.providerCode === "string") details.providerCode = value.providerCode;
|
|
90
|
+
if (typeof value.traceId === "string") details.traceId = value.traceId;
|
|
91
|
+
if (typeof value.statusCode === "number" && Number.isFinite(value.statusCode)) {
|
|
92
|
+
details.statusCode = value.statusCode;
|
|
93
|
+
}
|
|
94
|
+
if (typeof value.errorType === "string") details.errorType = value.errorType;
|
|
95
|
+
if (Array.isArray(value.simulationUrls)) {
|
|
96
|
+
const simulationUrls = value.simulationUrls.filter(
|
|
97
|
+
(url) => typeof url === "string"
|
|
98
|
+
);
|
|
99
|
+
if (simulationUrls.length > 0) details.simulationUrls = simulationUrls;
|
|
100
|
+
}
|
|
101
|
+
if (typeof value.reason === "string") details.reason = value.reason;
|
|
102
|
+
if (Array.isArray(value.candidateErrors)) {
|
|
103
|
+
const candidateErrors = value.candidateErrors.map(normalizeCandidateError).filter((candidate) => candidate !== void 0);
|
|
104
|
+
if (candidateErrors.length > 0) details.candidateErrors = candidateErrors;
|
|
105
|
+
}
|
|
106
|
+
return Object.keys(details).length > 0 ? details : void 0;
|
|
107
|
+
}
|
|
108
|
+
var OneAuthError = class extends Error {
|
|
109
|
+
constructor(code, message, details) {
|
|
110
|
+
super(message);
|
|
111
|
+
this.name = "OneAuthError";
|
|
112
|
+
this.code = code;
|
|
113
|
+
this.details = details;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
function toOneAuthError(error, fallbackMessage, fallbackCode = "UNKNOWN") {
|
|
117
|
+
return new OneAuthError(
|
|
118
|
+
error?.code || fallbackCode,
|
|
119
|
+
error?.message || fallbackMessage,
|
|
120
|
+
normalizeOneAuthErrorDetails(error?.details)
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
65
124
|
// src/react.tsx
|
|
66
125
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
67
126
|
var FingerprintIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
@@ -208,7 +267,7 @@ function PayButton({
|
|
|
208
267
|
localStorage.removeItem("1auth-user");
|
|
209
268
|
return executePayment(true);
|
|
210
269
|
}
|
|
211
|
-
onError?.(
|
|
270
|
+
onError?.(toOneAuthError(result.error, "Payment failed", "INTENT_FAILED"));
|
|
212
271
|
}
|
|
213
272
|
};
|
|
214
273
|
const combinedStyles = {
|
|
@@ -297,6 +356,7 @@ function useSponsorship(config) {
|
|
|
297
356
|
}
|
|
298
357
|
// Annotate the CommonJS export names for ESM import in node:
|
|
299
358
|
0 && (module.exports = {
|
|
359
|
+
OneAuthError,
|
|
300
360
|
PayButton,
|
|
301
361
|
createCachedSponsorship,
|
|
302
362
|
isAccessTokenFresh,
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.tsx","../src/sponsorship-fetch.ts"],"sourcesContent":["/**\n * @file React integration for the 1auth SDK.\n *\n * Exports the {@link PayButton} component — a ready-to-use payment button that\n * handles authentication, session recovery, and intent submission without\n * requiring the consuming app to manage auth state directly.\n *\n * @module @rhinestone/1auth/react\n */\n\nimport * as React from \"react\";\nimport { OneAuthClient } from \"./client\";\nimport { tokenFetchError } from \"./sponsorship-fetch\";\nimport type {\n SendIntentOptions,\n SendIntentResult,\n CloseOnStatus,\n SponsorshipCallbackConfig,\n SponsorshipUrlConfig,\n} from \"./types\";\n\n// Fingerprint icon SVG\nconst FingerprintIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4\" />\n <path d=\"M14 13.12c0 2.38 0 6.38-1 8.88\" />\n <path d=\"M17.29 21.02c.12-.6.43-2.3.5-3.02\" />\n <path d=\"M2 12a10 10 0 0 1 18-6\" />\n <path d=\"M2 16h.01\" />\n <path d=\"M21.8 16c.2-2 .131-5.354 0-6\" />\n <path d=\"M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2\" />\n <path d=\"M8.65 22c.21-.66.45-1.32.57-2\" />\n <path d=\"M9 6.8a6 6 0 0 1 9 5.2v2\" />\n </svg>\n);\n\n// Default styles\nconst defaultStyles: React.CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"8px\",\n padding: \"16px 32px\",\n fontSize: \"16px\",\n fontWeight: 500,\n color: \"#ffffff\",\n backgroundColor: \"#18181b\",\n border: \"none\",\n borderRadius: \"9999px\",\n cursor: \"pointer\",\n transition: \"background-color 0.2s\",\n width: \"100%\",\n};\n\nconst defaultDisabledStyles: React.CSSProperties = {\n opacity: 0.5,\n cursor: \"not-allowed\",\n};\n\nconst defaultHoverStyles: React.CSSProperties = {\n backgroundColor: \"#27272a\",\n};\n\nconst defaultSuccessStyles: React.CSSProperties = {\n backgroundColor: \"#16a34a\",\n cursor: \"default\",\n};\n\n// Checkmark icon SVG\nconst CheckIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M20 6L9 17l-5-5\" />\n </svg>\n);\n\nexport interface PayButtonProps {\n /** The OneAuthClient instance */\n client: OneAuthClient;\n /**\n * Intent parameters (calls, targetChain, etc.). `accountAddress` is omitted\n * because PayButton resolves it internally (cached session or auth modal) and\n * overwrites it on the sendIntent call — callers pass only calls + target\n * chain, keeping the drop-in payment API intact.\n */\n intent: Omit<SendIntentOptions, \"closeOn\" | \"accountAddress\">;\n /** Called when payment succeeds */\n onSuccess?: (result: SendIntentResult) => void;\n /** Called when payment fails */\n onError?: (error: Error) => void;\n /** When to close the dialog and return success. Defaults to \"preconfirmed\" */\n closeOn?: CloseOnStatus;\n /** Button text - defaults to \"Pay with 1auth\" */\n children?: React.ReactNode;\n /** Custom class name */\n className?: string;\n /** Custom inline styles (merged with defaults) */\n style?: React.CSSProperties;\n /** Disabled state */\n disabled?: boolean;\n /** Hide the fingerprint icon */\n hideIcon?: boolean;\n}\n\n/**\n * A pre-built payment button that integrates 1auth passkey authentication\n * and intent submission into a single interactive element.\n *\n * The button manages its own loading and success states. On first click it\n * recovers the last authenticated user from `localStorage`; if none is found\n * it opens the auth modal before submitting the intent. On subsequent clicks\n * the stored session is reused so the user only needs to re-authenticate when\n * their session has been invalidated server-side.\n *\n * @param props - See {@link PayButtonProps} for the full set of options.\n *\n * @example\n * ```tsx\n * import { PayButton } from \"@rhinestone/1auth/react\";\n * import { client } from \"./auth\"; // your OneAuthClient instance\n *\n * <PayButton\n * client={client}\n * intent={{\n * targetChain: 8453, // Base\n * calls: [{ to: \"0xRecipient\", data: \"0x\", value: \"1000000\" }],\n * }}\n * onSuccess={(result) => console.log(\"tx:\", result.transactionHash)}\n * onError={(err) => console.error(err)}\n * >\n * Pay $5 USDC\n * </PayButton>\n * ```\n */\nexport function PayButton({\n client,\n intent,\n onSuccess,\n onError,\n closeOn = \"preconfirmed\",\n children = \"Pay with 1auth\",\n className,\n style,\n disabled,\n hideIcon,\n}: PayButtonProps) {\n const [isProcessing, setIsProcessing] = React.useState(false);\n const [isSuccess, setIsSuccess] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n\n const handleClick = async () => {\n if (disabled || isProcessing || isSuccess) return;\n\n setIsProcessing(true);\n\n try {\n await executePayment();\n } catch (err) {\n if (err instanceof Error && !err.message.includes(\"rejected\")) {\n onError?.(err);\n }\n } finally {\n setIsProcessing(false);\n }\n };\n\n /**\n * Core payment execution with built-in session recovery and re-auth retry.\n *\n * Flow:\n * 1. On first call (`forceReauth = false`), attempt to load a cached user\n * from `localStorage` under the key `\"1auth-user\"`. If the JSON is\n * malformed the cache entry is removed so the next call starts clean.\n * 2. If no cached user exists (or `forceReauth` is `true`), open the auth\n * modal. On success, persist `{ address }` to `localStorage`\n * so subsequent clicks skip authentication.\n * 3. Submit the intent. If the server responds with \"User not found\" — which\n * happens when a cached account address no longer exists on the server —\n * clear `localStorage` and call `executePayment(true)` to force a fresh\n * authentication before retrying once.\n *\n * @param forceReauth - When `true`, skip the localStorage lookup and go\n * straight to the auth modal. Used internally on \"User not found\" errors\n * to recover from a stale cache without requiring a second user gesture.\n */\n const executePayment = async (forceReauth = false) => {\n // Try to get existing account address from localStorage\n let accountAddress: string | null = null;\n if (!forceReauth) {\n const savedUser = localStorage.getItem(\"1auth-user\");\n if (savedUser) {\n try {\n const parsed = JSON.parse(savedUser);\n accountAddress = parsed.address || null;\n } catch {\n localStorage.removeItem(\"1auth-user\");\n }\n }\n }\n\n // If no account address (or forced reauth), authenticate first\n if (!accountAddress) {\n const authResult = await client.authWithModal();\n if (authResult.success && authResult.user) {\n accountAddress = authResult.user.address || null;\n const stored: Record<string, string> = {};\n if (accountAddress) stored.address = accountAddress;\n if (authResult.signerType) stored.signerType = authResult.signerType;\n localStorage.setItem(\"1auth-user\", JSON.stringify(stored));\n } else {\n // Auth cancelled or failed\n return;\n }\n }\n\n // Send the intent\n let result: SendIntentResult;\n try {\n result = await client.sendIntent({\n ...intent,\n // Guaranteed non-null: the `if (!accountAddress) { ...return }` guard\n // above either resolved an address or bailed out before reaching here.\n accountAddress,\n closeOn,\n });\n } catch (err) {\n // If user not found, clear localStorage and force re-authentication\n if (err instanceof Error && err.message.includes(\"User not found\")) {\n localStorage.removeItem(\"1auth-user\");\n return executePayment(true);\n }\n throw err;\n }\n\n if (result.success) {\n setIsSuccess(true);\n onSuccess?.(result);\n } else {\n // If user not found error in result, clear localStorage and retry\n if (result.error?.message?.includes(\"User not found\")) {\n localStorage.removeItem(\"1auth-user\");\n return executePayment(true);\n }\n onError?.(new Error(result.error?.message || \"Payment failed\"));\n }\n };\n\n const combinedStyles: React.CSSProperties = {\n ...defaultStyles,\n ...(isSuccess ? defaultSuccessStyles : {}),\n ...(isHovered && !disabled && !isProcessing && !isSuccess ? defaultHoverStyles : {}),\n ...(disabled || isProcessing ? defaultDisabledStyles : {}),\n ...style,\n };\n\n return (\n <button\n type=\"button\"\n className={className}\n style={combinedStyles}\n onClick={handleClick}\n disabled={disabled || isProcessing || isSuccess}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {isSuccess ? (\n <>\n <CheckIcon className=\"pay-button-icon\" />\n Paid\n </>\n ) : isProcessing ? (\n \"Processing...\"\n ) : (\n <>\n {!hideIcon && <FingerprintIcon className=\"pay-button-icon\" />}\n {children}\n </>\n )}\n </button>\n );\n}\n\n/**\n * Margin (ms) before a JWT's `exp` at which the cached access token is\n * treated as stale. Covers clock skew between the minting app server and\n * the orchestrator's verifier plus in-flight time of the prepare call —\n * a token that verifies fine locally can still be rejected downstream if\n * it expires mid-request.\n */\nconst ACCESS_TOKEN_EXPIRY_MARGIN_MS = 60_000;\n\n/**\n * Check whether a cached JWT access token is still safely usable.\n *\n * Decodes the payload WITHOUT verifying the signature — the client only\n * needs the `exp` claim to know when to re-mint; verification happens\n * server-side. Returns `false` (unusable) when the token is expired or\n * within {@link ACCESS_TOKEN_EXPIRY_MARGIN_MS} of expiry. Tokens that\n * can't be decoded or carry no numeric `exp` are treated as unusable so\n * a malformed cache entry never gets served indefinitely.\n */\nexport function isAccessTokenFresh(token: string): boolean {\n try {\n const payload = token.split(\".\")[1];\n if (!payload) return false;\n // base64url → base64 before atob; JWTs use the url-safe alphabet.\n const json = atob(payload.replace(/-/g, \"+\").replace(/_/g, \"/\"));\n const claims = JSON.parse(json) as { exp?: unknown };\n if (typeof claims.exp !== \"number\") return false;\n return Date.now() < claims.exp * 1000 - ACCESS_TOKEN_EXPIRY_MARGIN_MS;\n } catch {\n return false;\n }\n}\n\n/**\n * Build a {@link SponsorshipCallbackConfig} from token endpoint URLs with an\n * expiry-aware access-token cache held in a closure.\n *\n * Exported as the non-React core of {@link useSponsorship} so the caching\n * behaviour is unit-testable (and usable outside React). The access token is\n * cached and re-used only while its `exp` claim is comfortably in the\n * future — a long-lived tab must re-mint rather than serve a token the\n * orchestrator will reject with a 401 (`\"exp\" claim timestamp check\n * failed`), which previously surfaced to users as \"Failed to get quote from\n * orchestrator\". The extension token is always fetched fresh per intent\n * because it binds to a specific `intentOp`.\n *\n * Both fetches use `credentials: \"include\"` so the app's own session cookies\n * authenticate the user — no separate auth channel needed.\n */\nexport function createCachedSponsorship(\n config: SponsorshipUrlConfig,\n): SponsorshipCallbackConfig {\n const { accessTokenUrl, extensionTokenUrl } = config;\n let cachedToken: string | null = null;\n\n const fetchAccessToken = async (): Promise<string> => {\n const res = await fetch(accessTokenUrl, {\n method: \"GET\",\n credentials: \"include\",\n });\n if (!res.ok) {\n // Folds the server's JSON error reason into the message so\n // misconfigurations aren't reduced to an opaque HTTP status.\n throw await tokenFetchError(\"sponsorship access token\", res);\n }\n const body = (await res.json()) as { token?: string };\n if (!body.token) throw new Error(\"Missing `token` in access-token response\");\n cachedToken = body.token;\n return body.token;\n };\n\n return {\n accessToken: async () =>\n cachedToken && isAccessTokenFresh(cachedToken)\n ? cachedToken\n : await fetchAccessToken(),\n getExtensionToken: async (intentOp: string) => {\n const res = await fetch(extensionTokenUrl, {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ intentOp }),\n });\n if (res.status === 401) {\n // Access token likely expired — drop cached copy so the next\n // accessToken() call re-mints, then surface the error for the\n // integrator to retry.\n cachedToken = null;\n }\n if (!res.ok) {\n throw await tokenFetchError(\"sponsorship extension token\", res);\n }\n const body = (await res.json()) as { token?: string };\n if (!body.token) throw new Error(\"Missing `token` in extension-token response\");\n return body.token;\n },\n };\n}\n\n/**\n * React hook wrapper around {@link createCachedSponsorship}. The returned\n * config is stable across renders (memoized by URL), so passing it to\n * `new OneAuthClient({ sponsorship })` or `client.setSponsorship(...)` does\n * not thrash the client. Re-creating on URL change naturally resets the\n * cached token so we never serve a token minted against the previous\n * endpoint.\n */\nexport function useSponsorship(\n config: SponsorshipUrlConfig,\n): SponsorshipCallbackConfig {\n const { accessTokenUrl, extensionTokenUrl } = config;\n\n return React.useMemo<SponsorshipCallbackConfig>(\n () => createCachedSponsorship({ accessTokenUrl, extensionTokenUrl }),\n [accessTokenUrl, extensionTokenUrl],\n );\n}\n\n// Re-export types for convenience\nexport type { SendIntentOptions, SendIntentResult, CloseOnStatus } from \"./types\";\n","/**\n * Shared helpers for fetching sponsorship tokens (access + extension) from an\n * integrator's backend endpoints.\n *\n * The integrator's token routes return their failure reason in the JSON body\n * (`{ error: \"createSponsorshipSigner: missing env var(s): ...\" }`). Surfacing\n * only the HTTP status — \"Failed to fetch access token (500 ...)\" — hides that\n * reason and turns every misconfiguration into the same opaque dialog error.\n * These helpers read the body and fold the server's message into the thrown\n * Error so the actual cause (missing env var, bad JWK, expired session) is\n * visible at the call site and in the dialog.\n */\n\n/**\n * Pull a human-readable reason out of a failed token response. Tries the JSON\n * `error`/`message` fields first, then falls back to a short text snippet, then\n * to the HTTP status text. Never throws — diagnostics must not mask the original\n * failure with a parse error.\n */\nasync function extractServerReason(response: Response): Promise<string> {\n try {\n // Clone so a JSON parse failure can still fall back to reading text.\n const text = await response.clone().text();\n if (!text) return response.statusText;\n try {\n const data = JSON.parse(text) as { error?: unknown; message?: unknown };\n const reason = data.error ?? data.message;\n if (typeof reason === \"string\" && reason.trim()) return reason;\n } catch {\n // Body wasn't JSON — fall through to the raw text snippet.\n }\n // Cap the snippet so an HTML error page doesn't flood the message.\n return text.slice(0, 200);\n } catch {\n return response.statusText;\n }\n}\n\n/**\n * Build an Error for a failed token fetch that includes the server's reason.\n * `label` names the token kind, e.g. \"access token\" or \"extension token\".\n */\nexport async function tokenFetchError(\n label: string,\n response: Response,\n): Promise<Error> {\n const reason = await extractServerReason(response);\n const suffix = reason ? `: ${reason}` : \"\";\n return new Error(\n `Failed to fetch ${label} (${response.status} ${response.statusText})${suffix}`,\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx","../src/sponsorship-fetch.ts","../src/errors.ts"],"sourcesContent":["/**\n * @file React integration for the 1auth SDK.\n *\n * Exports the {@link PayButton} component — a ready-to-use payment button that\n * handles authentication, session recovery, and intent submission without\n * requiring the consuming app to manage auth state directly.\n *\n * @module @rhinestone/1auth/react\n */\n\nimport * as React from \"react\";\nimport { OneAuthClient } from \"./client\";\nimport { tokenFetchError } from \"./sponsorship-fetch\";\nimport { toOneAuthError } from \"./errors\";\nimport type {\n SendIntentOptions,\n SendIntentResult,\n CloseOnStatus,\n SponsorshipCallbackConfig,\n SponsorshipUrlConfig,\n} from \"./types\";\n\n// Fingerprint icon SVG\nconst FingerprintIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4\" />\n <path d=\"M14 13.12c0 2.38 0 6.38-1 8.88\" />\n <path d=\"M17.29 21.02c.12-.6.43-2.3.5-3.02\" />\n <path d=\"M2 12a10 10 0 0 1 18-6\" />\n <path d=\"M2 16h.01\" />\n <path d=\"M21.8 16c.2-2 .131-5.354 0-6\" />\n <path d=\"M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2\" />\n <path d=\"M8.65 22c.21-.66.45-1.32.57-2\" />\n <path d=\"M9 6.8a6 6 0 0 1 9 5.2v2\" />\n </svg>\n);\n\n// Default styles\nconst defaultStyles: React.CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"8px\",\n padding: \"16px 32px\",\n fontSize: \"16px\",\n fontWeight: 500,\n color: \"#ffffff\",\n backgroundColor: \"#18181b\",\n border: \"none\",\n borderRadius: \"9999px\",\n cursor: \"pointer\",\n transition: \"background-color 0.2s\",\n width: \"100%\",\n};\n\nconst defaultDisabledStyles: React.CSSProperties = {\n opacity: 0.5,\n cursor: \"not-allowed\",\n};\n\nconst defaultHoverStyles: React.CSSProperties = {\n backgroundColor: \"#27272a\",\n};\n\nconst defaultSuccessStyles: React.CSSProperties = {\n backgroundColor: \"#16a34a\",\n cursor: \"default\",\n};\n\n// Checkmark icon SVG\nconst CheckIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M20 6L9 17l-5-5\" />\n </svg>\n);\n\nexport interface PayButtonProps {\n /** The OneAuthClient instance */\n client: OneAuthClient;\n /**\n * Intent parameters (calls, targetChain, etc.). `accountAddress` is omitted\n * because PayButton resolves it internally (cached session or auth modal) and\n * overwrites it on the sendIntent call — callers pass only calls + target\n * chain, keeping the drop-in payment API intact.\n */\n intent: Omit<SendIntentOptions, \"closeOn\" | \"accountAddress\">;\n /** Called when payment succeeds */\n onSuccess?: (result: SendIntentResult) => void;\n /** Called when payment fails */\n onError?: (error: Error) => void;\n /** When to close the dialog and return success. Defaults to \"preconfirmed\" */\n closeOn?: CloseOnStatus;\n /** Button text - defaults to \"Pay with 1auth\" */\n children?: React.ReactNode;\n /** Custom class name */\n className?: string;\n /** Custom inline styles (merged with defaults) */\n style?: React.CSSProperties;\n /** Disabled state */\n disabled?: boolean;\n /** Hide the fingerprint icon */\n hideIcon?: boolean;\n}\n\n/**\n * A pre-built payment button that integrates 1auth passkey authentication\n * and intent submission into a single interactive element.\n *\n * The button manages its own loading and success states. On first click it\n * recovers the last authenticated user from `localStorage`; if none is found\n * it opens the auth modal before submitting the intent. On subsequent clicks\n * the stored session is reused so the user only needs to re-authenticate when\n * their session has been invalidated server-side.\n *\n * @param props - See {@link PayButtonProps} for the full set of options.\n *\n * @example\n * ```tsx\n * import { PayButton } from \"@rhinestone/1auth/react\";\n * import { client } from \"./auth\"; // your OneAuthClient instance\n *\n * <PayButton\n * client={client}\n * intent={{\n * targetChain: 8453, // Base\n * calls: [{ to: \"0xRecipient\", data: \"0x\", value: \"1000000\" }],\n * }}\n * onSuccess={(result) => console.log(\"tx:\", result.transactionHash)}\n * onError={(err) => console.error(err)}\n * >\n * Pay $5 USDC\n * </PayButton>\n * ```\n */\nexport function PayButton({\n client,\n intent,\n onSuccess,\n onError,\n closeOn = \"preconfirmed\",\n children = \"Pay with 1auth\",\n className,\n style,\n disabled,\n hideIcon,\n}: PayButtonProps) {\n const [isProcessing, setIsProcessing] = React.useState(false);\n const [isSuccess, setIsSuccess] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n\n const handleClick = async () => {\n if (disabled || isProcessing || isSuccess) return;\n\n setIsProcessing(true);\n\n try {\n await executePayment();\n } catch (err) {\n if (err instanceof Error && !err.message.includes(\"rejected\")) {\n onError?.(err);\n }\n } finally {\n setIsProcessing(false);\n }\n };\n\n /**\n * Core payment execution with built-in session recovery and re-auth retry.\n *\n * Flow:\n * 1. On first call (`forceReauth = false`), attempt to load a cached user\n * from `localStorage` under the key `\"1auth-user\"`. If the JSON is\n * malformed the cache entry is removed so the next call starts clean.\n * 2. If no cached user exists (or `forceReauth` is `true`), open the auth\n * modal. On success, persist `{ address }` to `localStorage`\n * so subsequent clicks skip authentication.\n * 3. Submit the intent. If the server responds with \"User not found\" — which\n * happens when a cached account address no longer exists on the server —\n * clear `localStorage` and call `executePayment(true)` to force a fresh\n * authentication before retrying once.\n *\n * @param forceReauth - When `true`, skip the localStorage lookup and go\n * straight to the auth modal. Used internally on \"User not found\" errors\n * to recover from a stale cache without requiring a second user gesture.\n */\n const executePayment = async (forceReauth = false) => {\n // Try to get existing account address from localStorage\n let accountAddress: string | null = null;\n if (!forceReauth) {\n const savedUser = localStorage.getItem(\"1auth-user\");\n if (savedUser) {\n try {\n const parsed = JSON.parse(savedUser);\n accountAddress = parsed.address || null;\n } catch {\n localStorage.removeItem(\"1auth-user\");\n }\n }\n }\n\n // If no account address (or forced reauth), authenticate first\n if (!accountAddress) {\n const authResult = await client.authWithModal();\n if (authResult.success && authResult.user) {\n accountAddress = authResult.user.address || null;\n const stored: Record<string, string> = {};\n if (accountAddress) stored.address = accountAddress;\n if (authResult.signerType) stored.signerType = authResult.signerType;\n localStorage.setItem(\"1auth-user\", JSON.stringify(stored));\n } else {\n // Auth cancelled or failed\n return;\n }\n }\n\n // Send the intent\n let result: SendIntentResult;\n try {\n result = await client.sendIntent({\n ...intent,\n // Guaranteed non-null: the `if (!accountAddress) { ...return }` guard\n // above either resolved an address or bailed out before reaching here.\n accountAddress,\n closeOn,\n });\n } catch (err) {\n // If user not found, clear localStorage and force re-authentication\n if (err instanceof Error && err.message.includes(\"User not found\")) {\n localStorage.removeItem(\"1auth-user\");\n return executePayment(true);\n }\n throw err;\n }\n\n if (result.success) {\n setIsSuccess(true);\n onSuccess?.(result);\n } else {\n // If user not found error in result, clear localStorage and retry\n if (result.error?.message?.includes(\"User not found\")) {\n localStorage.removeItem(\"1auth-user\");\n return executePayment(true);\n }\n onError?.(toOneAuthError(result.error, \"Payment failed\", \"INTENT_FAILED\"));\n }\n };\n\n const combinedStyles: React.CSSProperties = {\n ...defaultStyles,\n ...(isSuccess ? defaultSuccessStyles : {}),\n ...(isHovered && !disabled && !isProcessing && !isSuccess ? defaultHoverStyles : {}),\n ...(disabled || isProcessing ? defaultDisabledStyles : {}),\n ...style,\n };\n\n return (\n <button\n type=\"button\"\n className={className}\n style={combinedStyles}\n onClick={handleClick}\n disabled={disabled || isProcessing || isSuccess}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {isSuccess ? (\n <>\n <CheckIcon className=\"pay-button-icon\" />\n Paid\n </>\n ) : isProcessing ? (\n \"Processing...\"\n ) : (\n <>\n {!hideIcon && <FingerprintIcon className=\"pay-button-icon\" />}\n {children}\n </>\n )}\n </button>\n );\n}\n\n/**\n * Margin (ms) before a JWT's `exp` at which the cached access token is\n * treated as stale. Covers clock skew between the minting app server and\n * the orchestrator's verifier plus in-flight time of the prepare call —\n * a token that verifies fine locally can still be rejected downstream if\n * it expires mid-request.\n */\nconst ACCESS_TOKEN_EXPIRY_MARGIN_MS = 60_000;\n\n/**\n * Check whether a cached JWT access token is still safely usable.\n *\n * Decodes the payload WITHOUT verifying the signature — the client only\n * needs the `exp` claim to know when to re-mint; verification happens\n * server-side. Returns `false` (unusable) when the token is expired or\n * within {@link ACCESS_TOKEN_EXPIRY_MARGIN_MS} of expiry. Tokens that\n * can't be decoded or carry no numeric `exp` are treated as unusable so\n * a malformed cache entry never gets served indefinitely.\n */\nexport function isAccessTokenFresh(token: string): boolean {\n try {\n const payload = token.split(\".\")[1];\n if (!payload) return false;\n // base64url → base64 before atob; JWTs use the url-safe alphabet.\n const json = atob(payload.replace(/-/g, \"+\").replace(/_/g, \"/\"));\n const claims = JSON.parse(json) as { exp?: unknown };\n if (typeof claims.exp !== \"number\") return false;\n return Date.now() < claims.exp * 1000 - ACCESS_TOKEN_EXPIRY_MARGIN_MS;\n } catch {\n return false;\n }\n}\n\n/**\n * Build a {@link SponsorshipCallbackConfig} from token endpoint URLs with an\n * expiry-aware access-token cache held in a closure.\n *\n * Exported as the non-React core of {@link useSponsorship} so the caching\n * behaviour is unit-testable (and usable outside React). The access token is\n * cached and re-used only while its `exp` claim is comfortably in the\n * future — a long-lived tab must re-mint rather than serve a token the\n * orchestrator will reject with a 401 (`\"exp\" claim timestamp check\n * failed`), which previously surfaced to users as \"Failed to get quote from\n * orchestrator\". The extension token is always fetched fresh per intent\n * because it binds to a specific `intentOp`.\n *\n * Both fetches use `credentials: \"include\"` so the app's own session cookies\n * authenticate the user — no separate auth channel needed.\n */\nexport function createCachedSponsorship(\n config: SponsorshipUrlConfig,\n): SponsorshipCallbackConfig {\n const { accessTokenUrl, extensionTokenUrl } = config;\n let cachedToken: string | null = null;\n\n const fetchAccessToken = async (): Promise<string> => {\n const res = await fetch(accessTokenUrl, {\n method: \"GET\",\n credentials: \"include\",\n });\n if (!res.ok) {\n // Folds the server's JSON error reason into the message so\n // misconfigurations aren't reduced to an opaque HTTP status.\n throw await tokenFetchError(\"sponsorship access token\", res);\n }\n const body = (await res.json()) as { token?: string };\n if (!body.token) throw new Error(\"Missing `token` in access-token response\");\n cachedToken = body.token;\n return body.token;\n };\n\n return {\n accessToken: async () =>\n cachedToken && isAccessTokenFresh(cachedToken)\n ? cachedToken\n : await fetchAccessToken(),\n getExtensionToken: async (intentOp: string) => {\n const res = await fetch(extensionTokenUrl, {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ intentOp }),\n });\n if (res.status === 401) {\n // Access token likely expired — drop cached copy so the next\n // accessToken() call re-mints, then surface the error for the\n // integrator to retry.\n cachedToken = null;\n }\n if (!res.ok) {\n throw await tokenFetchError(\"sponsorship extension token\", res);\n }\n const body = (await res.json()) as { token?: string };\n if (!body.token) throw new Error(\"Missing `token` in extension-token response\");\n return body.token;\n },\n };\n}\n\n/**\n * React hook wrapper around {@link createCachedSponsorship}. The returned\n * config is stable across renders (memoized by URL), so passing it to\n * `new OneAuthClient({ sponsorship })` or `client.setSponsorship(...)` does\n * not thrash the client. Re-creating on URL change naturally resets the\n * cached token so we never serve a token minted against the previous\n * endpoint.\n */\nexport function useSponsorship(\n config: SponsorshipUrlConfig,\n): SponsorshipCallbackConfig {\n const { accessTokenUrl, extensionTokenUrl } = config;\n\n return React.useMemo<SponsorshipCallbackConfig>(\n () => createCachedSponsorship({ accessTokenUrl, extensionTokenUrl }),\n [accessTokenUrl, extensionTokenUrl],\n );\n}\n\n// Export the constructor from the same entrypoint that creates PayButton\n// errors. Separate tsup entry bundles do not share JavaScript class identity,\n// so consumers must use this export for reliable `instanceof` checks.\nexport { OneAuthError } from \"./errors\";\n\n// Re-export types for convenience\nexport type { SendIntentOptions, SendIntentResult, CloseOnStatus } from \"./types\";\n","/**\n * Shared helpers for fetching sponsorship tokens (access + extension) from an\n * integrator's backend endpoints.\n *\n * The integrator's token routes return their failure reason in the JSON body\n * (`{ error: \"createSponsorshipSigner: missing env var(s): ...\" }`). Surfacing\n * only the HTTP status — \"Failed to fetch access token (500 ...)\" — hides that\n * reason and turns every misconfiguration into the same opaque dialog error.\n * These helpers read the body and fold the server's message into the thrown\n * Error so the actual cause (missing env var, bad JWK, expired session) is\n * visible at the call site and in the dialog.\n */\n\n/**\n * Pull a human-readable reason out of a failed token response. Tries the JSON\n * `error`/`message` fields first, then falls back to a short text snippet, then\n * to the HTTP status text. Never throws — diagnostics must not mask the original\n * failure with a parse error.\n */\nasync function extractServerReason(response: Response): Promise<string> {\n try {\n // Clone so a JSON parse failure can still fall back to reading text.\n const text = await response.clone().text();\n if (!text) return response.statusText;\n try {\n const data = JSON.parse(text) as { error?: unknown; message?: unknown };\n const reason = data.error ?? data.message;\n if (typeof reason === \"string\" && reason.trim()) return reason;\n } catch {\n // Body wasn't JSON — fall through to the raw text snippet.\n }\n // Cap the snippet so an HTML error page doesn't flood the message.\n return text.slice(0, 200);\n } catch {\n return response.statusText;\n }\n}\n\n/**\n * Build an Error for a failed token fetch that includes the server's reason.\n * `label` names the token kind, e.g. \"access token\" or \"extension token\".\n */\nexport async function tokenFetchError(\n label: string,\n response: Response,\n): Promise<Error> {\n const reason = await extractServerReason(response);\n const suffix = reason ? `: ${reason}` : \"\";\n return new Error(\n `Failed to fetch ${label} (${response.status} ${response.statusText})${suffix}`,\n );\n}\n","import {\n isSigningErrorCode,\n type OneAuthCandidateError,\n type OneAuthErrorDetails,\n type OneAuthResultError,\n type SigningErrorCode,\n} from \"./types\";\n\n/** Return true only for plain records that are safe to inspect field-by-field. */\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\n/** Copy one candidate failure without leaking arbitrary provider context. */\nfunction normalizeCandidateError(value: unknown): OneAuthCandidateError | undefined {\n if (!isPlainRecord(value)) return undefined;\n const candidate: OneAuthCandidateError = {};\n if (typeof value.code === \"string\") candidate.code = value.code;\n if (typeof value.message === \"string\") candidate.message = value.message;\n const details = normalizeOneAuthErrorDetails(value.details);\n if (details) candidate.details = details;\n return Object.keys(candidate).length > 0 ? candidate : undefined;\n}\n\n/**\n * Normalizes untrusted provider diagnostics to the declared public allowlist.\n * Strings from prepare endpoints are retained as a reason, while arrays are\n * exposed only as sanitized candidate errors rather than cast to an object.\n */\nexport function normalizeOneAuthErrorDetails(value: unknown): OneAuthErrorDetails | undefined {\n if (typeof value === \"string\") return { reason: value };\n if (Array.isArray(value)) {\n const candidateErrors = value\n .map(normalizeCandidateError)\n .filter((candidate): candidate is OneAuthCandidateError => candidate !== undefined);\n return candidateErrors.length > 0 ? { candidateErrors } : undefined;\n }\n if (!isPlainRecord(value)) return undefined;\n\n const details: OneAuthErrorDetails = {};\n if (typeof value.providerCode === \"string\") details.providerCode = value.providerCode;\n if (typeof value.traceId === \"string\") details.traceId = value.traceId;\n if (typeof value.statusCode === \"number\" && Number.isFinite(value.statusCode)) {\n details.statusCode = value.statusCode;\n }\n if (typeof value.errorType === \"string\") details.errorType = value.errorType;\n if (Array.isArray(value.simulationUrls)) {\n const simulationUrls = value.simulationUrls.filter(\n (url): url is string => typeof url === \"string\",\n );\n if (simulationUrls.length > 0) details.simulationUrls = simulationUrls;\n }\n if (typeof value.reason === \"string\") details.reason = value.reason;\n if (Array.isArray(value.candidateErrors)) {\n const candidateErrors = value.candidateErrors\n .map(normalizeCandidateError)\n .filter((candidate): candidate is OneAuthCandidateError => candidate !== undefined);\n if (candidateErrors.length > 0) details.candidateErrors = candidateErrors;\n }\n return Object.keys(details).length > 0 ? details : undefined;\n}\n\n/**\n * Parses an untrusted signing error without allowing its code to widen the\n * public SigningErrorCode contract.\n */\nexport function parseSigningResultError(\n value: unknown,\n fallbackCode: SigningErrorCode = \"SIGNING_FAILED\",\n fallbackMessage = \"Signing failed\",\n): OneAuthResultError<SigningErrorCode> {\n if (!isPlainRecord(value)) return { code: fallbackCode, message: fallbackMessage };\n const code = isSigningErrorCode(value.code) ? value.code : value.code === undefined ? fallbackCode : \"UNKNOWN\";\n return {\n code,\n message: typeof value.message === \"string\" ? value.message : fallbackMessage,\n details: normalizeOneAuthErrorDetails(value.details),\n };\n}\n\n/**\n * Error thrown by SDK adapters that must use exception-based APIs, such as\n * EIP-1193, viem accounts, wallet clients, and React callbacks.\n *\n * `code` is stable enough for application branching. `details` contains\n * provider/orchestrator diagnostics such as trace IDs and simulation URLs.\n */\nexport class OneAuthError extends Error {\n readonly code: string;\n readonly details?: OneAuthErrorDetails;\n\n constructor(code: string, message: string, details?: OneAuthErrorDetails) {\n super(message);\n this.name = \"OneAuthError\";\n this.code = code;\n this.details = details;\n }\n}\n\n/**\n * Converts a result-object error into the SDK's structured exception type.\n */\nexport function toOneAuthError(\n error: { code?: string; message?: string; details?: unknown } | undefined,\n fallbackMessage: string,\n fallbackCode = \"UNKNOWN\",\n): OneAuthError {\n return new OneAuthError(\n error?.code || fallbackCode,\n error?.message || fallbackMessage,\n normalizeOneAuthErrorDetails(error?.details),\n );\n}\n\n/**\n * Maps an auth-service execute response to the stable public SDK stage code.\n * Provider-specific codes belong in `details.providerCode`; the invalid\n * signature exception remains public because applications must route recovery.\n */\nexport function executeErrorCode(errorData: unknown): \"INVALID_SIGNATURE\" | \"EXECUTE_FAILED\" {\n if (!errorData || typeof errorData !== \"object\" || !(\"code\" in errorData)) {\n return \"EXECUTE_FAILED\";\n }\n return errorData.code === \"INVALID_SIGNATURE\" ? \"INVALID_SIGNATURE\" : \"EXECUTE_FAILED\";\n}\n\n/**\n * Normalizes support-safe auth-service diagnostics to the public SDK shape.\n * The service names its upstream code `code`; SDK consumers receive it as\n * `providerCode` so it cannot be confused with the public stage code.\n */\nexport function executeErrorDetails(debug: unknown): OneAuthErrorDetails | undefined {\n if (!debug || typeof debug !== \"object\") return undefined;\n const details: OneAuthErrorDetails = {};\n if (\"code\" in debug && typeof debug.code === \"string\") details.providerCode = debug.code;\n if (\"traceId\" in debug && typeof debug.traceId === \"string\") details.traceId = debug.traceId;\n if (\"statusCode\" in debug && typeof debug.statusCode === \"number\") {\n details.statusCode = debug.statusCode;\n }\n if (\"errorType\" in debug && typeof debug.errorType === \"string\") {\n details.errorType = debug.errorType;\n }\n if (\"simulationUrls\" in debug && Array.isArray(debug.simulationUrls)) {\n details.simulationUrls = debug.simulationUrls.filter(\n (url): url is string => typeof url === \"string\",\n );\n }\n return Object.keys(details).length > 0 ? details : undefined;\n}\n"],"mappings":"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","names":[]}
|
package/dist/react.mjs
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OneAuthError,
|
|
3
|
+
toOneAuthError
|
|
4
|
+
} from "./chunk-ZDW2LY6H.mjs";
|
|
1
5
|
import {
|
|
2
6
|
tokenFetchError
|
|
3
7
|
} from "./chunk-IIACVHR3.mjs";
|
|
@@ -149,7 +153,7 @@ function PayButton({
|
|
|
149
153
|
localStorage.removeItem("1auth-user");
|
|
150
154
|
return executePayment(true);
|
|
151
155
|
}
|
|
152
|
-
onError?.(
|
|
156
|
+
onError?.(toOneAuthError(result.error, "Payment failed", "INTENT_FAILED"));
|
|
153
157
|
}
|
|
154
158
|
};
|
|
155
159
|
const combinedStyles = {
|
|
@@ -237,6 +241,7 @@ function useSponsorship(config) {
|
|
|
237
241
|
);
|
|
238
242
|
}
|
|
239
243
|
export {
|
|
244
|
+
OneAuthError,
|
|
240
245
|
PayButton,
|
|
241
246
|
createCachedSponsorship,
|
|
242
247
|
isAccessTokenFresh,
|
package/dist/react.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.tsx"],"sourcesContent":["/**\n * @file React integration for the 1auth SDK.\n *\n * Exports the {@link PayButton} component — a ready-to-use payment button that\n * handles authentication, session recovery, and intent submission without\n * requiring the consuming app to manage auth state directly.\n *\n * @module @rhinestone/1auth/react\n */\n\nimport * as React from \"react\";\nimport { OneAuthClient } from \"./client\";\nimport { tokenFetchError } from \"./sponsorship-fetch\";\nimport type {\n SendIntentOptions,\n SendIntentResult,\n CloseOnStatus,\n SponsorshipCallbackConfig,\n SponsorshipUrlConfig,\n} from \"./types\";\n\n// Fingerprint icon SVG\nconst FingerprintIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4\" />\n <path d=\"M14 13.12c0 2.38 0 6.38-1 8.88\" />\n <path d=\"M17.29 21.02c.12-.6.43-2.3.5-3.02\" />\n <path d=\"M2 12a10 10 0 0 1 18-6\" />\n <path d=\"M2 16h.01\" />\n <path d=\"M21.8 16c.2-2 .131-5.354 0-6\" />\n <path d=\"M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2\" />\n <path d=\"M8.65 22c.21-.66.45-1.32.57-2\" />\n <path d=\"M9 6.8a6 6 0 0 1 9 5.2v2\" />\n </svg>\n);\n\n// Default styles\nconst defaultStyles: React.CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"8px\",\n padding: \"16px 32px\",\n fontSize: \"16px\",\n fontWeight: 500,\n color: \"#ffffff\",\n backgroundColor: \"#18181b\",\n border: \"none\",\n borderRadius: \"9999px\",\n cursor: \"pointer\",\n transition: \"background-color 0.2s\",\n width: \"100%\",\n};\n\nconst defaultDisabledStyles: React.CSSProperties = {\n opacity: 0.5,\n cursor: \"not-allowed\",\n};\n\nconst defaultHoverStyles: React.CSSProperties = {\n backgroundColor: \"#27272a\",\n};\n\nconst defaultSuccessStyles: React.CSSProperties = {\n backgroundColor: \"#16a34a\",\n cursor: \"default\",\n};\n\n// Checkmark icon SVG\nconst CheckIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M20 6L9 17l-5-5\" />\n </svg>\n);\n\nexport interface PayButtonProps {\n /** The OneAuthClient instance */\n client: OneAuthClient;\n /**\n * Intent parameters (calls, targetChain, etc.). `accountAddress` is omitted\n * because PayButton resolves it internally (cached session or auth modal) and\n * overwrites it on the sendIntent call — callers pass only calls + target\n * chain, keeping the drop-in payment API intact.\n */\n intent: Omit<SendIntentOptions, \"closeOn\" | \"accountAddress\">;\n /** Called when payment succeeds */\n onSuccess?: (result: SendIntentResult) => void;\n /** Called when payment fails */\n onError?: (error: Error) => void;\n /** When to close the dialog and return success. Defaults to \"preconfirmed\" */\n closeOn?: CloseOnStatus;\n /** Button text - defaults to \"Pay with 1auth\" */\n children?: React.ReactNode;\n /** Custom class name */\n className?: string;\n /** Custom inline styles (merged with defaults) */\n style?: React.CSSProperties;\n /** Disabled state */\n disabled?: boolean;\n /** Hide the fingerprint icon */\n hideIcon?: boolean;\n}\n\n/**\n * A pre-built payment button that integrates 1auth passkey authentication\n * and intent submission into a single interactive element.\n *\n * The button manages its own loading and success states. On first click it\n * recovers the last authenticated user from `localStorage`; if none is found\n * it opens the auth modal before submitting the intent. On subsequent clicks\n * the stored session is reused so the user only needs to re-authenticate when\n * their session has been invalidated server-side.\n *\n * @param props - See {@link PayButtonProps} for the full set of options.\n *\n * @example\n * ```tsx\n * import { PayButton } from \"@rhinestone/1auth/react\";\n * import { client } from \"./auth\"; // your OneAuthClient instance\n *\n * <PayButton\n * client={client}\n * intent={{\n * targetChain: 8453, // Base\n * calls: [{ to: \"0xRecipient\", data: \"0x\", value: \"1000000\" }],\n * }}\n * onSuccess={(result) => console.log(\"tx:\", result.transactionHash)}\n * onError={(err) => console.error(err)}\n * >\n * Pay $5 USDC\n * </PayButton>\n * ```\n */\nexport function PayButton({\n client,\n intent,\n onSuccess,\n onError,\n closeOn = \"preconfirmed\",\n children = \"Pay with 1auth\",\n className,\n style,\n disabled,\n hideIcon,\n}: PayButtonProps) {\n const [isProcessing, setIsProcessing] = React.useState(false);\n const [isSuccess, setIsSuccess] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n\n const handleClick = async () => {\n if (disabled || isProcessing || isSuccess) return;\n\n setIsProcessing(true);\n\n try {\n await executePayment();\n } catch (err) {\n if (err instanceof Error && !err.message.includes(\"rejected\")) {\n onError?.(err);\n }\n } finally {\n setIsProcessing(false);\n }\n };\n\n /**\n * Core payment execution with built-in session recovery and re-auth retry.\n *\n * Flow:\n * 1. On first call (`forceReauth = false`), attempt to load a cached user\n * from `localStorage` under the key `\"1auth-user\"`. If the JSON is\n * malformed the cache entry is removed so the next call starts clean.\n * 2. If no cached user exists (or `forceReauth` is `true`), open the auth\n * modal. On success, persist `{ address }` to `localStorage`\n * so subsequent clicks skip authentication.\n * 3. Submit the intent. If the server responds with \"User not found\" — which\n * happens when a cached account address no longer exists on the server —\n * clear `localStorage` and call `executePayment(true)` to force a fresh\n * authentication before retrying once.\n *\n * @param forceReauth - When `true`, skip the localStorage lookup and go\n * straight to the auth modal. Used internally on \"User not found\" errors\n * to recover from a stale cache without requiring a second user gesture.\n */\n const executePayment = async (forceReauth = false) => {\n // Try to get existing account address from localStorage\n let accountAddress: string | null = null;\n if (!forceReauth) {\n const savedUser = localStorage.getItem(\"1auth-user\");\n if (savedUser) {\n try {\n const parsed = JSON.parse(savedUser);\n accountAddress = parsed.address || null;\n } catch {\n localStorage.removeItem(\"1auth-user\");\n }\n }\n }\n\n // If no account address (or forced reauth), authenticate first\n if (!accountAddress) {\n const authResult = await client.authWithModal();\n if (authResult.success && authResult.user) {\n accountAddress = authResult.user.address || null;\n const stored: Record<string, string> = {};\n if (accountAddress) stored.address = accountAddress;\n if (authResult.signerType) stored.signerType = authResult.signerType;\n localStorage.setItem(\"1auth-user\", JSON.stringify(stored));\n } else {\n // Auth cancelled or failed\n return;\n }\n }\n\n // Send the intent\n let result: SendIntentResult;\n try {\n result = await client.sendIntent({\n ...intent,\n // Guaranteed non-null: the `if (!accountAddress) { ...return }` guard\n // above either resolved an address or bailed out before reaching here.\n accountAddress,\n closeOn,\n });\n } catch (err) {\n // If user not found, clear localStorage and force re-authentication\n if (err instanceof Error && err.message.includes(\"User not found\")) {\n localStorage.removeItem(\"1auth-user\");\n return executePayment(true);\n }\n throw err;\n }\n\n if (result.success) {\n setIsSuccess(true);\n onSuccess?.(result);\n } else {\n // If user not found error in result, clear localStorage and retry\n if (result.error?.message?.includes(\"User not found\")) {\n localStorage.removeItem(\"1auth-user\");\n return executePayment(true);\n }\n onError?.(new Error(result.error?.message || \"Payment failed\"));\n }\n };\n\n const combinedStyles: React.CSSProperties = {\n ...defaultStyles,\n ...(isSuccess ? defaultSuccessStyles : {}),\n ...(isHovered && !disabled && !isProcessing && !isSuccess ? defaultHoverStyles : {}),\n ...(disabled || isProcessing ? defaultDisabledStyles : {}),\n ...style,\n };\n\n return (\n <button\n type=\"button\"\n className={className}\n style={combinedStyles}\n onClick={handleClick}\n disabled={disabled || isProcessing || isSuccess}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {isSuccess ? (\n <>\n <CheckIcon className=\"pay-button-icon\" />\n Paid\n </>\n ) : isProcessing ? (\n \"Processing...\"\n ) : (\n <>\n {!hideIcon && <FingerprintIcon className=\"pay-button-icon\" />}\n {children}\n </>\n )}\n </button>\n );\n}\n\n/**\n * Margin (ms) before a JWT's `exp` at which the cached access token is\n * treated as stale. Covers clock skew between the minting app server and\n * the orchestrator's verifier plus in-flight time of the prepare call —\n * a token that verifies fine locally can still be rejected downstream if\n * it expires mid-request.\n */\nconst ACCESS_TOKEN_EXPIRY_MARGIN_MS = 60_000;\n\n/**\n * Check whether a cached JWT access token is still safely usable.\n *\n * Decodes the payload WITHOUT verifying the signature — the client only\n * needs the `exp` claim to know when to re-mint; verification happens\n * server-side. Returns `false` (unusable) when the token is expired or\n * within {@link ACCESS_TOKEN_EXPIRY_MARGIN_MS} of expiry. Tokens that\n * can't be decoded or carry no numeric `exp` are treated as unusable so\n * a malformed cache entry never gets served indefinitely.\n */\nexport function isAccessTokenFresh(token: string): boolean {\n try {\n const payload = token.split(\".\")[1];\n if (!payload) return false;\n // base64url → base64 before atob; JWTs use the url-safe alphabet.\n const json = atob(payload.replace(/-/g, \"+\").replace(/_/g, \"/\"));\n const claims = JSON.parse(json) as { exp?: unknown };\n if (typeof claims.exp !== \"number\") return false;\n return Date.now() < claims.exp * 1000 - ACCESS_TOKEN_EXPIRY_MARGIN_MS;\n } catch {\n return false;\n }\n}\n\n/**\n * Build a {@link SponsorshipCallbackConfig} from token endpoint URLs with an\n * expiry-aware access-token cache held in a closure.\n *\n * Exported as the non-React core of {@link useSponsorship} so the caching\n * behaviour is unit-testable (and usable outside React). The access token is\n * cached and re-used only while its `exp` claim is comfortably in the\n * future — a long-lived tab must re-mint rather than serve a token the\n * orchestrator will reject with a 401 (`\"exp\" claim timestamp check\n * failed`), which previously surfaced to users as \"Failed to get quote from\n * orchestrator\". The extension token is always fetched fresh per intent\n * because it binds to a specific `intentOp`.\n *\n * Both fetches use `credentials: \"include\"` so the app's own session cookies\n * authenticate the user — no separate auth channel needed.\n */\nexport function createCachedSponsorship(\n config: SponsorshipUrlConfig,\n): SponsorshipCallbackConfig {\n const { accessTokenUrl, extensionTokenUrl } = config;\n let cachedToken: string | null = null;\n\n const fetchAccessToken = async (): Promise<string> => {\n const res = await fetch(accessTokenUrl, {\n method: \"GET\",\n credentials: \"include\",\n });\n if (!res.ok) {\n // Folds the server's JSON error reason into the message so\n // misconfigurations aren't reduced to an opaque HTTP status.\n throw await tokenFetchError(\"sponsorship access token\", res);\n }\n const body = (await res.json()) as { token?: string };\n if (!body.token) throw new Error(\"Missing `token` in access-token response\");\n cachedToken = body.token;\n return body.token;\n };\n\n return {\n accessToken: async () =>\n cachedToken && isAccessTokenFresh(cachedToken)\n ? cachedToken\n : await fetchAccessToken(),\n getExtensionToken: async (intentOp: string) => {\n const res = await fetch(extensionTokenUrl, {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ intentOp }),\n });\n if (res.status === 401) {\n // Access token likely expired — drop cached copy so the next\n // accessToken() call re-mints, then surface the error for the\n // integrator to retry.\n cachedToken = null;\n }\n if (!res.ok) {\n throw await tokenFetchError(\"sponsorship extension token\", res);\n }\n const body = (await res.json()) as { token?: string };\n if (!body.token) throw new Error(\"Missing `token` in extension-token response\");\n return body.token;\n },\n };\n}\n\n/**\n * React hook wrapper around {@link createCachedSponsorship}. The returned\n * config is stable across renders (memoized by URL), so passing it to\n * `new OneAuthClient({ sponsorship })` or `client.setSponsorship(...)` does\n * not thrash the client. Re-creating on URL change naturally resets the\n * cached token so we never serve a token minted against the previous\n * endpoint.\n */\nexport function useSponsorship(\n config: SponsorshipUrlConfig,\n): SponsorshipCallbackConfig {\n const { accessTokenUrl, extensionTokenUrl } = config;\n\n return React.useMemo<SponsorshipCallbackConfig>(\n () => createCachedSponsorship({ accessTokenUrl, extensionTokenUrl }),\n [accessTokenUrl, extensionTokenUrl],\n );\n}\n\n// Re-export types for convenience\nexport type { SendIntentOptions, SendIntentResult, CloseOnStatus } from \"./types\";\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx"],"sourcesContent":["/**\n * @file React integration for the 1auth SDK.\n *\n * Exports the {@link PayButton} component — a ready-to-use payment button that\n * handles authentication, session recovery, and intent submission without\n * requiring the consuming app to manage auth state directly.\n *\n * @module @rhinestone/1auth/react\n */\n\nimport * as React from \"react\";\nimport { OneAuthClient } from \"./client\";\nimport { tokenFetchError } from \"./sponsorship-fetch\";\nimport { toOneAuthError } from \"./errors\";\nimport type {\n SendIntentOptions,\n SendIntentResult,\n CloseOnStatus,\n SponsorshipCallbackConfig,\n SponsorshipUrlConfig,\n} from \"./types\";\n\n// Fingerprint icon SVG\nconst FingerprintIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4\" />\n <path d=\"M14 13.12c0 2.38 0 6.38-1 8.88\" />\n <path d=\"M17.29 21.02c.12-.6.43-2.3.5-3.02\" />\n <path d=\"M2 12a10 10 0 0 1 18-6\" />\n <path d=\"M2 16h.01\" />\n <path d=\"M21.8 16c.2-2 .131-5.354 0-6\" />\n <path d=\"M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2\" />\n <path d=\"M8.65 22c.21-.66.45-1.32.57-2\" />\n <path d=\"M9 6.8a6 6 0 0 1 9 5.2v2\" />\n </svg>\n);\n\n// Default styles\nconst defaultStyles: React.CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"8px\",\n padding: \"16px 32px\",\n fontSize: \"16px\",\n fontWeight: 500,\n color: \"#ffffff\",\n backgroundColor: \"#18181b\",\n border: \"none\",\n borderRadius: \"9999px\",\n cursor: \"pointer\",\n transition: \"background-color 0.2s\",\n width: \"100%\",\n};\n\nconst defaultDisabledStyles: React.CSSProperties = {\n opacity: 0.5,\n cursor: \"not-allowed\",\n};\n\nconst defaultHoverStyles: React.CSSProperties = {\n backgroundColor: \"#27272a\",\n};\n\nconst defaultSuccessStyles: React.CSSProperties = {\n backgroundColor: \"#16a34a\",\n cursor: \"default\",\n};\n\n// Checkmark icon SVG\nconst CheckIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M20 6L9 17l-5-5\" />\n </svg>\n);\n\nexport interface PayButtonProps {\n /** The OneAuthClient instance */\n client: OneAuthClient;\n /**\n * Intent parameters (calls, targetChain, etc.). `accountAddress` is omitted\n * because PayButton resolves it internally (cached session or auth modal) and\n * overwrites it on the sendIntent call — callers pass only calls + target\n * chain, keeping the drop-in payment API intact.\n */\n intent: Omit<SendIntentOptions, \"closeOn\" | \"accountAddress\">;\n /** Called when payment succeeds */\n onSuccess?: (result: SendIntentResult) => void;\n /** Called when payment fails */\n onError?: (error: Error) => void;\n /** When to close the dialog and return success. Defaults to \"preconfirmed\" */\n closeOn?: CloseOnStatus;\n /** Button text - defaults to \"Pay with 1auth\" */\n children?: React.ReactNode;\n /** Custom class name */\n className?: string;\n /** Custom inline styles (merged with defaults) */\n style?: React.CSSProperties;\n /** Disabled state */\n disabled?: boolean;\n /** Hide the fingerprint icon */\n hideIcon?: boolean;\n}\n\n/**\n * A pre-built payment button that integrates 1auth passkey authentication\n * and intent submission into a single interactive element.\n *\n * The button manages its own loading and success states. On first click it\n * recovers the last authenticated user from `localStorage`; if none is found\n * it opens the auth modal before submitting the intent. On subsequent clicks\n * the stored session is reused so the user only needs to re-authenticate when\n * their session has been invalidated server-side.\n *\n * @param props - See {@link PayButtonProps} for the full set of options.\n *\n * @example\n * ```tsx\n * import { PayButton } from \"@rhinestone/1auth/react\";\n * import { client } from \"./auth\"; // your OneAuthClient instance\n *\n * <PayButton\n * client={client}\n * intent={{\n * targetChain: 8453, // Base\n * calls: [{ to: \"0xRecipient\", data: \"0x\", value: \"1000000\" }],\n * }}\n * onSuccess={(result) => console.log(\"tx:\", result.transactionHash)}\n * onError={(err) => console.error(err)}\n * >\n * Pay $5 USDC\n * </PayButton>\n * ```\n */\nexport function PayButton({\n client,\n intent,\n onSuccess,\n onError,\n closeOn = \"preconfirmed\",\n children = \"Pay with 1auth\",\n className,\n style,\n disabled,\n hideIcon,\n}: PayButtonProps) {\n const [isProcessing, setIsProcessing] = React.useState(false);\n const [isSuccess, setIsSuccess] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n\n const handleClick = async () => {\n if (disabled || isProcessing || isSuccess) return;\n\n setIsProcessing(true);\n\n try {\n await executePayment();\n } catch (err) {\n if (err instanceof Error && !err.message.includes(\"rejected\")) {\n onError?.(err);\n }\n } finally {\n setIsProcessing(false);\n }\n };\n\n /**\n * Core payment execution with built-in session recovery and re-auth retry.\n *\n * Flow:\n * 1. On first call (`forceReauth = false`), attempt to load a cached user\n * from `localStorage` under the key `\"1auth-user\"`. If the JSON is\n * malformed the cache entry is removed so the next call starts clean.\n * 2. If no cached user exists (or `forceReauth` is `true`), open the auth\n * modal. On success, persist `{ address }` to `localStorage`\n * so subsequent clicks skip authentication.\n * 3. Submit the intent. If the server responds with \"User not found\" — which\n * happens when a cached account address no longer exists on the server —\n * clear `localStorage` and call `executePayment(true)` to force a fresh\n * authentication before retrying once.\n *\n * @param forceReauth - When `true`, skip the localStorage lookup and go\n * straight to the auth modal. Used internally on \"User not found\" errors\n * to recover from a stale cache without requiring a second user gesture.\n */\n const executePayment = async (forceReauth = false) => {\n // Try to get existing account address from localStorage\n let accountAddress: string | null = null;\n if (!forceReauth) {\n const savedUser = localStorage.getItem(\"1auth-user\");\n if (savedUser) {\n try {\n const parsed = JSON.parse(savedUser);\n accountAddress = parsed.address || null;\n } catch {\n localStorage.removeItem(\"1auth-user\");\n }\n }\n }\n\n // If no account address (or forced reauth), authenticate first\n if (!accountAddress) {\n const authResult = await client.authWithModal();\n if (authResult.success && authResult.user) {\n accountAddress = authResult.user.address || null;\n const stored: Record<string, string> = {};\n if (accountAddress) stored.address = accountAddress;\n if (authResult.signerType) stored.signerType = authResult.signerType;\n localStorage.setItem(\"1auth-user\", JSON.stringify(stored));\n } else {\n // Auth cancelled or failed\n return;\n }\n }\n\n // Send the intent\n let result: SendIntentResult;\n try {\n result = await client.sendIntent({\n ...intent,\n // Guaranteed non-null: the `if (!accountAddress) { ...return }` guard\n // above either resolved an address or bailed out before reaching here.\n accountAddress,\n closeOn,\n });\n } catch (err) {\n // If user not found, clear localStorage and force re-authentication\n if (err instanceof Error && err.message.includes(\"User not found\")) {\n localStorage.removeItem(\"1auth-user\");\n return executePayment(true);\n }\n throw err;\n }\n\n if (result.success) {\n setIsSuccess(true);\n onSuccess?.(result);\n } else {\n // If user not found error in result, clear localStorage and retry\n if (result.error?.message?.includes(\"User not found\")) {\n localStorage.removeItem(\"1auth-user\");\n return executePayment(true);\n }\n onError?.(toOneAuthError(result.error, \"Payment failed\", \"INTENT_FAILED\"));\n }\n };\n\n const combinedStyles: React.CSSProperties = {\n ...defaultStyles,\n ...(isSuccess ? defaultSuccessStyles : {}),\n ...(isHovered && !disabled && !isProcessing && !isSuccess ? defaultHoverStyles : {}),\n ...(disabled || isProcessing ? defaultDisabledStyles : {}),\n ...style,\n };\n\n return (\n <button\n type=\"button\"\n className={className}\n style={combinedStyles}\n onClick={handleClick}\n disabled={disabled || isProcessing || isSuccess}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {isSuccess ? (\n <>\n <CheckIcon className=\"pay-button-icon\" />\n Paid\n </>\n ) : isProcessing ? (\n \"Processing...\"\n ) : (\n <>\n {!hideIcon && <FingerprintIcon className=\"pay-button-icon\" />}\n {children}\n </>\n )}\n </button>\n );\n}\n\n/**\n * Margin (ms) before a JWT's `exp` at which the cached access token is\n * treated as stale. Covers clock skew between the minting app server and\n * the orchestrator's verifier plus in-flight time of the prepare call —\n * a token that verifies fine locally can still be rejected downstream if\n * it expires mid-request.\n */\nconst ACCESS_TOKEN_EXPIRY_MARGIN_MS = 60_000;\n\n/**\n * Check whether a cached JWT access token is still safely usable.\n *\n * Decodes the payload WITHOUT verifying the signature — the client only\n * needs the `exp` claim to know when to re-mint; verification happens\n * server-side. Returns `false` (unusable) when the token is expired or\n * within {@link ACCESS_TOKEN_EXPIRY_MARGIN_MS} of expiry. Tokens that\n * can't be decoded or carry no numeric `exp` are treated as unusable so\n * a malformed cache entry never gets served indefinitely.\n */\nexport function isAccessTokenFresh(token: string): boolean {\n try {\n const payload = token.split(\".\")[1];\n if (!payload) return false;\n // base64url → base64 before atob; JWTs use the url-safe alphabet.\n const json = atob(payload.replace(/-/g, \"+\").replace(/_/g, \"/\"));\n const claims = JSON.parse(json) as { exp?: unknown };\n if (typeof claims.exp !== \"number\") return false;\n return Date.now() < claims.exp * 1000 - ACCESS_TOKEN_EXPIRY_MARGIN_MS;\n } catch {\n return false;\n }\n}\n\n/**\n * Build a {@link SponsorshipCallbackConfig} from token endpoint URLs with an\n * expiry-aware access-token cache held in a closure.\n *\n * Exported as the non-React core of {@link useSponsorship} so the caching\n * behaviour is unit-testable (and usable outside React). The access token is\n * cached and re-used only while its `exp` claim is comfortably in the\n * future — a long-lived tab must re-mint rather than serve a token the\n * orchestrator will reject with a 401 (`\"exp\" claim timestamp check\n * failed`), which previously surfaced to users as \"Failed to get quote from\n * orchestrator\". The extension token is always fetched fresh per intent\n * because it binds to a specific `intentOp`.\n *\n * Both fetches use `credentials: \"include\"` so the app's own session cookies\n * authenticate the user — no separate auth channel needed.\n */\nexport function createCachedSponsorship(\n config: SponsorshipUrlConfig,\n): SponsorshipCallbackConfig {\n const { accessTokenUrl, extensionTokenUrl } = config;\n let cachedToken: string | null = null;\n\n const fetchAccessToken = async (): Promise<string> => {\n const res = await fetch(accessTokenUrl, {\n method: \"GET\",\n credentials: \"include\",\n });\n if (!res.ok) {\n // Folds the server's JSON error reason into the message so\n // misconfigurations aren't reduced to an opaque HTTP status.\n throw await tokenFetchError(\"sponsorship access token\", res);\n }\n const body = (await res.json()) as { token?: string };\n if (!body.token) throw new Error(\"Missing `token` in access-token response\");\n cachedToken = body.token;\n return body.token;\n };\n\n return {\n accessToken: async () =>\n cachedToken && isAccessTokenFresh(cachedToken)\n ? cachedToken\n : await fetchAccessToken(),\n getExtensionToken: async (intentOp: string) => {\n const res = await fetch(extensionTokenUrl, {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ intentOp }),\n });\n if (res.status === 401) {\n // Access token likely expired — drop cached copy so the next\n // accessToken() call re-mints, then surface the error for the\n // integrator to retry.\n cachedToken = null;\n }\n if (!res.ok) {\n throw await tokenFetchError(\"sponsorship extension token\", res);\n }\n const body = (await res.json()) as { token?: string };\n if (!body.token) throw new Error(\"Missing `token` in extension-token response\");\n return body.token;\n },\n };\n}\n\n/**\n * React hook wrapper around {@link createCachedSponsorship}. The returned\n * config is stable across renders (memoized by URL), so passing it to\n * `new OneAuthClient({ sponsorship })` or `client.setSponsorship(...)` does\n * not thrash the client. Re-creating on URL change naturally resets the\n * cached token so we never serve a token minted against the previous\n * endpoint.\n */\nexport function useSponsorship(\n config: SponsorshipUrlConfig,\n): SponsorshipCallbackConfig {\n const { accessTokenUrl, extensionTokenUrl } = config;\n\n return React.useMemo<SponsorshipCallbackConfig>(\n () => createCachedSponsorship({ accessTokenUrl, extensionTokenUrl }),\n [accessTokenUrl, extensionTokenUrl],\n );\n}\n\n// Export the constructor from the same entrypoint that creates PayButton\n// errors. Separate tsup entry bundles do not share JavaScript class identity,\n// so consumers must use this export for reliable `instanceof` checks.\nexport { OneAuthError } from \"./errors\";\n\n// Re-export types for convenience\nexport type { SendIntentOptions, SendIntentResult, CloseOnStatus } from \"./types\";\n"],"mappings":"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","names":[]}
|
package/dist/server.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Address, Hex } from 'viem';
|
|
2
|
-
export { e as encodeWebAuthnSignature, q as hashMessage, k as isTestnet, v as verifyMessageHash } from './verify-
|
|
3
|
-
export { W as WebAuthnSignature } from './types-
|
|
2
|
+
export { e as encodeWebAuthnSignature, q as hashMessage, k as isTestnet, v as verifyMessageHash } from './verify-CEzkfM92.mjs';
|
|
3
|
+
export { W as WebAuthnSignature } from './types-BN6cCuAd.mjs';
|
|
4
4
|
import '@rhinestone/sdk';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/server.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Address, Hex } from 'viem';
|
|
2
|
-
export { e as encodeWebAuthnSignature, q as hashMessage, k as isTestnet, v as verifyMessageHash } from './verify-
|
|
3
|
-
export { W as WebAuthnSignature } from './types-
|
|
2
|
+
export { e as encodeWebAuthnSignature, q as hashMessage, k as isTestnet, v as verifyMessageHash } from './verify-DhEkGnym.js';
|
|
3
|
+
export { W as WebAuthnSignature } from './types-BN6cCuAd.js';
|
|
4
4
|
import '@rhinestone/sdk';
|
|
5
5
|
|
|
6
6
|
/**
|