@swype-org/react-sdk 0.1.220 → 0.1.221

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/index.cjs CHANGED
@@ -459,6 +459,7 @@ async function waitForTransactionReceipt(config, parameters) {
459
459
  // src/api.ts
460
460
  var api_exports = {};
461
461
  __export(api_exports, {
462
+ claimAccount: () => claimAccount,
462
463
  createAccount: () => createAccount,
463
464
  createAccountAuthorizationSession: () => createAccountAuthorizationSession,
464
465
  createGuestTransfer: () => createGuestTransfer,
@@ -467,6 +468,7 @@ __export(api_exports, {
467
468
  fetchAccounts: () => fetchAccounts,
468
469
  fetchAuthorizationSession: () => fetchAuthorizationSession,
469
470
  fetchChains: () => fetchChains,
471
+ fetchGuestPreauthAccount: () => fetchGuestPreauthAccount,
470
472
  fetchGuestTransferBalances: () => fetchGuestTransferBalances,
471
473
  fetchMerchantPublicKey: () => fetchMerchantPublicKey,
472
474
  fetchProviders: () => fetchProviders,
@@ -766,6 +768,25 @@ async function fetchGuestTransferBalances(apiBaseUrl, transferId, guestSessionTo
766
768
  const data = await res.json();
767
769
  return data.items;
768
770
  }
771
+ async function fetchGuestPreauthAccount(apiBaseUrl, guestToken) {
772
+ const params = new URLSearchParams({ guestToken });
773
+ const res = await fetch(`${apiBaseUrl}/v1/guest-preauth?${params.toString()}`);
774
+ if (res.status === 404) return null;
775
+ if (!res.ok) await throwApiError(res);
776
+ return await res.json();
777
+ }
778
+ async function claimAccount(apiBaseUrl, accessToken, accountId, body) {
779
+ const res = await fetch(`${apiBaseUrl}/v1/accounts/${accountId}/claim`, {
780
+ method: "POST",
781
+ headers: {
782
+ "Content-Type": "application/json",
783
+ "Authorization": `Bearer ${accessToken}`
784
+ },
785
+ body: JSON.stringify(body)
786
+ });
787
+ if (!res.ok) await throwApiError(res);
788
+ return await res.json();
789
+ }
769
790
  async function reportActionCompletion(apiBaseUrl, actionId, result) {
770
791
  const res = await fetch(
771
792
  `${apiBaseUrl}/v1/authorization-actions/${actionId}`,
@@ -1940,7 +1961,9 @@ function createInitialState(config) {
1940
1961
  previousStep: null,
1941
1962
  isGuestFlow: false,
1942
1963
  guestTransferId: null,
1943
- guestSessionToken: null
1964
+ guestSessionToken: null,
1965
+ guestPreauthAccountId: null,
1966
+ activePublicKey: null
1944
1967
  };
1945
1968
  }
1946
1969
  function paymentReducer(state, action) {
@@ -1971,6 +1994,7 @@ function paymentReducer(state, action) {
1971
1994
  return {
1972
1995
  ...state,
1973
1996
  activeCredentialId: action.credentialId,
1997
+ activePublicKey: action.publicKey ?? state.activePublicKey,
1974
1998
  passkeyPopupNeeded: false
1975
1999
  };
1976
2000
  case "SET_PASSKEY_POPUP_NEEDED":
@@ -2184,6 +2208,20 @@ function paymentReducer(state, action) {
2184
2208
  mobileFlow: false,
2185
2209
  deeplinkUri: null
2186
2210
  };
2211
+ case "GUEST_PREAUTH_DETECTED":
2212
+ return {
2213
+ ...state,
2214
+ guestPreauthAccountId: action.accountId,
2215
+ step: "login"
2216
+ };
2217
+ case "GUEST_PREAUTH_CLAIMED":
2218
+ return {
2219
+ ...state,
2220
+ guestPreauthAccountId: null,
2221
+ activePublicKey: null,
2222
+ step: "deposit",
2223
+ error: null
2224
+ };
2187
2225
  // ── Navigation & error ───────────────────────────────────────
2188
2226
  case "NAVIGATE":
2189
2227
  return { ...state, step: action.step, previousStep: state.step, error: null };
@@ -2204,7 +2242,9 @@ function paymentReducer(state, action) {
2204
2242
  selectedAccountId: action.firstAccountId,
2205
2243
  isGuestFlow: false,
2206
2244
  guestTransferId: null,
2207
- guestSessionToken: null
2245
+ guestSessionToken: null,
2246
+ guestPreauthAccountId: null,
2247
+ activePublicKey: null
2208
2248
  };
2209
2249
  case "LOGOUT":
2210
2250
  return {
@@ -4448,6 +4488,7 @@ function SuccessScreen({
4448
4488
  onLogout,
4449
4489
  onIncreaseLimits,
4450
4490
  onManageAccount,
4491
+ onPreauthorize,
4451
4492
  autoCloseSeconds
4452
4493
  }) {
4453
4494
  const { tokens } = useBlinkConfig();
@@ -4482,6 +4523,15 @@ function SuccessScreen({
4482
4523
  {
4483
4524
  footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4484
4525
  /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: handleDone, children: succeeded ? "Done" : "Try again" }),
4526
+ succeeded && onPreauthorize && /* @__PURE__ */ jsxRuntime.jsx(
4527
+ "button",
4528
+ {
4529
+ type: "button",
4530
+ onClick: onPreauthorize,
4531
+ style: preauthorizeStyle(tokens.accent, tokens.border),
4532
+ children: "Preauthorize future transfers"
4533
+ }
4534
+ ),
4485
4535
  effectiveAutoClose != null && effectiveAutoClose > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: countdownStyle(tokens.textMuted), children: [
4486
4536
  "Returning to app in ",
4487
4537
  countdown,
@@ -4611,6 +4661,19 @@ var upsellLinkStyle = (color) => ({
4611
4661
  fontFamily: "inherit",
4612
4662
  padding: 0
4613
4663
  });
4664
+ var preauthorizeStyle = (accentColor, borderColor) => ({
4665
+ width: "100%",
4666
+ padding: "14px 0",
4667
+ marginTop: 8,
4668
+ background: "transparent",
4669
+ border: `1px solid ${borderColor}`,
4670
+ borderRadius: 20,
4671
+ color: accentColor,
4672
+ fontWeight: 600,
4673
+ fontSize: "0.92rem",
4674
+ cursor: "pointer",
4675
+ fontFamily: "inherit"
4676
+ });
4614
4677
  var countdownStyle = (color) => ({
4615
4678
  fontSize: "0.82rem",
4616
4679
  color,
@@ -6089,6 +6152,7 @@ function StepRendererContent({
6089
6152
  })() : void 0,
6090
6153
  onDone: onDismiss ?? handlers.onNewPayment,
6091
6154
  onLogout: handlers.onLogout,
6155
+ onPreauthorize: state.isGuestFlow ? handlers.onPreauthorize : void 0,
6092
6156
  autoCloseSeconds
6093
6157
  }
6094
6158
  );
@@ -6401,7 +6465,7 @@ function resolveRestoredMobileFlow(transferStatus, isSetup) {
6401
6465
  }
6402
6466
 
6403
6467
  // src/hooks/usePasskeyHandlers.ts
6404
- function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds, mobileSetupFlowRef) {
6468
+ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds, mobileSetupFlowRef, guestPreauthAccountId) {
6405
6469
  const { user, getAccessToken } = reactAuth.usePrivy();
6406
6470
  const checkingPasskeyRef = react.useRef(false);
6407
6471
  const activateExistingCredential = react.useCallback(async (credentialId) => {
@@ -6426,8 +6490,11 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6426
6490
  const token = await getAccessToken();
6427
6491
  if (!token) throw new Error("Not authenticated");
6428
6492
  await registerPasskey(apiBaseUrl, token, credentialId, publicKey);
6429
- dispatch({ type: "PASSKEY_ACTIVATED", credentialId });
6493
+ dispatch({ type: "PASSKEY_ACTIVATED", credentialId, publicKey });
6430
6494
  window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
6495
+ if (guestPreauthAccountId) {
6496
+ return;
6497
+ }
6431
6498
  const resolved = resolvePostAuthStep({
6432
6499
  hasPasskey: true,
6433
6500
  accounts,
@@ -6437,7 +6504,7 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6437
6504
  });
6438
6505
  if (resolved.clearPersistedFlow) clearMobileFlowState();
6439
6506
  dispatch({ type: "NAVIGATE", step: resolved.step });
6440
- }, [getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, dispatch]);
6507
+ }, [getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, guestPreauthAccountId, dispatch]);
6441
6508
  const handleRegisterPasskey = react.useCallback(async () => {
6442
6509
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
6443
6510
  dispatch({ type: "SET_ERROR", error: null });
@@ -8274,6 +8341,77 @@ function usePaymentEffects(deps) {
8274
8341
  preOneTapSetupStepRef.current = null;
8275
8342
  }
8276
8343
  }, [pendingOneTapSetupAction, state.step, reloadAccounts, authExecutor, dispatch, oneTapLimitSavedDuringSetupRef]);
8344
+ react.useEffect(() => {
8345
+ if (state.step !== "success") return;
8346
+ if (!state.guestSessionToken) return;
8347
+ if (state.guestPreauthAccountId) return;
8348
+ let cancelled = false;
8349
+ const checkPreauth = async () => {
8350
+ try {
8351
+ const result = await fetchGuestPreauthAccount(apiBaseUrl, state.guestSessionToken);
8352
+ if (cancelled) return;
8353
+ if (result && !result.hasPasskey) {
8354
+ dispatch({ type: "GUEST_PREAUTH_DETECTED", accountId: result.accountId });
8355
+ }
8356
+ } catch {
8357
+ }
8358
+ };
8359
+ checkPreauth();
8360
+ return () => {
8361
+ cancelled = true;
8362
+ };
8363
+ }, [state.step, state.guestSessionToken, state.guestPreauthAccountId, apiBaseUrl, dispatch]);
8364
+ const claimingRef = react.useRef(false);
8365
+ react.useEffect(() => {
8366
+ if (!state.guestPreauthAccountId) return;
8367
+ if (!state.activeCredentialId) return;
8368
+ if (!state.activePublicKey) return;
8369
+ if (!authenticated) return;
8370
+ if (!state.guestSessionToken) return;
8371
+ if (claimingRef.current) return;
8372
+ claimingRef.current = true;
8373
+ let cancelled = false;
8374
+ const claimPreauth = async () => {
8375
+ try {
8376
+ const token = await getAccessTokenRef.current();
8377
+ if (!token || cancelled) return;
8378
+ await claimAccount(apiBaseUrl, token, state.guestPreauthAccountId, {
8379
+ guestToken: state.guestSessionToken,
8380
+ credentialId: state.activeCredentialId,
8381
+ publicKey: state.activePublicKey
8382
+ });
8383
+ if (cancelled) return;
8384
+ try {
8385
+ await reloadAccounts();
8386
+ } catch {
8387
+ }
8388
+ if (cancelled) return;
8389
+ dispatch({ type: "GUEST_PREAUTH_CLAIMED" });
8390
+ } catch (err) {
8391
+ if (cancelled) return;
8392
+ captureException(err);
8393
+ dispatch({
8394
+ type: "SET_ERROR",
8395
+ error: err instanceof Error ? err.message : "Failed to claim account"
8396
+ });
8397
+ } finally {
8398
+ claimingRef.current = false;
8399
+ }
8400
+ };
8401
+ claimPreauth();
8402
+ return () => {
8403
+ cancelled = true;
8404
+ };
8405
+ }, [
8406
+ state.guestPreauthAccountId,
8407
+ state.activeCredentialId,
8408
+ state.activePublicKey,
8409
+ state.guestSessionToken,
8410
+ authenticated,
8411
+ apiBaseUrl,
8412
+ dispatch,
8413
+ reloadAccounts
8414
+ ]);
8277
8415
  }
8278
8416
  function BlinkPayment(props) {
8279
8417
  const resetKey = react.useRef(0);
@@ -8324,7 +8462,8 @@ function BlinkPaymentInner({
8324
8462
  apiBaseUrl,
8325
8463
  state.accounts,
8326
8464
  state.knownCredentialIds,
8327
- mobileFlowRefs.mobileSetupFlowRef
8465
+ mobileFlowRefs.mobileSetupFlowRef,
8466
+ state.guestPreauthAccountId
8328
8467
  );
8329
8468
  const transfer = useTransferHandlers({
8330
8469
  dispatch,
@@ -8500,7 +8639,8 @@ function BlinkPaymentInner({
8500
8639
  onSelectAuthorizedToken: provider.handleSelectAuthorizedToken,
8501
8640
  onAuthorizeToken: provider.handleAuthorizeToken,
8502
8641
  onSelectGuestToken: guestTransfer.handleSelectGuestToken,
8503
- onLogin: () => dispatch({ type: "NAVIGATE", step: "login" })
8642
+ onLogin: () => dispatch({ type: "NAVIGATE", step: "login" }),
8643
+ onPreauthorize: () => dispatch({ type: "NAVIGATE", step: "login" })
8504
8644
  }), [
8505
8645
  auth,
8506
8646
  passkey,