@swype-org/react-sdk 0.1.219 → 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,
@@ -491,9 +493,11 @@ async function throwApiError(res) {
491
493
  throw new Error(`${res.status} \u2014 ${code}: ${msg}`);
492
494
  }
493
495
  async function fetchProviders(apiBaseUrl, token) {
494
- const res = await fetch(`${apiBaseUrl}/v1/providers`, {
495
- headers: { Authorization: `Bearer ${token}` }
496
- });
496
+ const headers = {};
497
+ if (token) {
498
+ headers.Authorization = `Bearer ${token}`;
499
+ }
500
+ const res = await fetch(`${apiBaseUrl}/v1/providers`, { headers });
497
501
  if (!res.ok) await throwApiError(res);
498
502
  const data = await res.json();
499
503
  return data.items;
@@ -764,6 +768,25 @@ async function fetchGuestTransferBalances(apiBaseUrl, transferId, guestSessionTo
764
768
  const data = await res.json();
765
769
  return data.items;
766
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
+ }
767
790
  async function reportActionCompletion(apiBaseUrl, actionId, result) {
768
791
  const res = await fetch(
769
792
  `${apiBaseUrl}/v1/authorization-actions/${actionId}`,
@@ -1938,7 +1961,9 @@ function createInitialState(config) {
1938
1961
  previousStep: null,
1939
1962
  isGuestFlow: false,
1940
1963
  guestTransferId: null,
1941
- guestSessionToken: null
1964
+ guestSessionToken: null,
1965
+ guestPreauthAccountId: null,
1966
+ activePublicKey: null
1942
1967
  };
1943
1968
  }
1944
1969
  function paymentReducer(state, action) {
@@ -1969,6 +1994,7 @@ function paymentReducer(state, action) {
1969
1994
  return {
1970
1995
  ...state,
1971
1996
  activeCredentialId: action.credentialId,
1997
+ activePublicKey: action.publicKey ?? state.activePublicKey,
1972
1998
  passkeyPopupNeeded: false
1973
1999
  };
1974
2000
  case "SET_PASSKEY_POPUP_NEEDED":
@@ -2182,6 +2208,20 @@ function paymentReducer(state, action) {
2182
2208
  mobileFlow: false,
2183
2209
  deeplinkUri: null
2184
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
+ };
2185
2225
  // ── Navigation & error ───────────────────────────────────────
2186
2226
  case "NAVIGATE":
2187
2227
  return { ...state, step: action.step, previousStep: state.step, error: null };
@@ -2202,7 +2242,9 @@ function paymentReducer(state, action) {
2202
2242
  selectedAccountId: action.firstAccountId,
2203
2243
  isGuestFlow: false,
2204
2244
  guestTransferId: null,
2205
- guestSessionToken: null
2245
+ guestSessionToken: null,
2246
+ guestPreauthAccountId: null,
2247
+ activePublicKey: null
2206
2248
  };
2207
2249
  case "LOGOUT":
2208
2250
  return {
@@ -4446,6 +4488,7 @@ function SuccessScreen({
4446
4488
  onLogout,
4447
4489
  onIncreaseLimits,
4448
4490
  onManageAccount,
4491
+ onPreauthorize,
4449
4492
  autoCloseSeconds
4450
4493
  }) {
4451
4494
  const { tokens } = useBlinkConfig();
@@ -4480,6 +4523,15 @@ function SuccessScreen({
4480
4523
  {
4481
4524
  footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4482
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
+ ),
4483
4535
  effectiveAutoClose != null && effectiveAutoClose > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: countdownStyle(tokens.textMuted), children: [
4484
4536
  "Returning to app in ",
4485
4537
  countdown,
@@ -4609,6 +4661,19 @@ var upsellLinkStyle = (color) => ({
4609
4661
  fontFamily: "inherit",
4610
4662
  padding: 0
4611
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
+ });
4612
4677
  var countdownStyle = (color) => ({
4613
4678
  fontSize: "0.82rem",
4614
4679
  color,
@@ -6087,6 +6152,7 @@ function StepRendererContent({
6087
6152
  })() : void 0,
6088
6153
  onDone: onDismiss ?? handlers.onNewPayment,
6089
6154
  onLogout: handlers.onLogout,
6155
+ onPreauthorize: state.isGuestFlow ? handlers.onPreauthorize : void 0,
6090
6156
  autoCloseSeconds
6091
6157
  }
6092
6158
  );
@@ -6399,7 +6465,7 @@ function resolveRestoredMobileFlow(transferStatus, isSetup) {
6399
6465
  }
6400
6466
 
6401
6467
  // src/hooks/usePasskeyHandlers.ts
6402
- function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds, mobileSetupFlowRef) {
6468
+ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds, mobileSetupFlowRef, guestPreauthAccountId) {
6403
6469
  const { user, getAccessToken } = reactAuth.usePrivy();
6404
6470
  const checkingPasskeyRef = react.useRef(false);
6405
6471
  const activateExistingCredential = react.useCallback(async (credentialId) => {
@@ -6424,8 +6490,11 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6424
6490
  const token = await getAccessToken();
6425
6491
  if (!token) throw new Error("Not authenticated");
6426
6492
  await registerPasskey(apiBaseUrl, token, credentialId, publicKey);
6427
- dispatch({ type: "PASSKEY_ACTIVATED", credentialId });
6493
+ dispatch({ type: "PASSKEY_ACTIVATED", credentialId, publicKey });
6428
6494
  window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
6495
+ if (guestPreauthAccountId) {
6496
+ return;
6497
+ }
6429
6498
  const resolved = resolvePostAuthStep({
6430
6499
  hasPasskey: true,
6431
6500
  accounts,
@@ -6435,7 +6504,7 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6435
6504
  });
6436
6505
  if (resolved.clearPersistedFlow) clearMobileFlowState();
6437
6506
  dispatch({ type: "NAVIGATE", step: resolved.step });
6438
- }, [getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, dispatch]);
6507
+ }, [getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, guestPreauthAccountId, dispatch]);
6439
6508
  const handleRegisterPasskey = react.useCallback(async () => {
6440
6509
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
6441
6510
  dispatch({ type: "SET_ERROR", error: null });
@@ -7991,6 +8060,32 @@ function usePaymentEffects(deps) {
7991
8060
  state.selectedAccountId,
7992
8061
  depositAmount
7993
8062
  ]);
8063
+ react.useEffect(() => {
8064
+ if (authenticated || state.providers.length > 0) return;
8065
+ if (state.step !== "wallet-picker") return;
8066
+ let cancelled = false;
8067
+ const loadProviders = async () => {
8068
+ try {
8069
+ const providers = await fetchProviders(apiBaseUrl);
8070
+ if (cancelled) return;
8071
+ dispatch({
8072
+ type: "DATA_LOADED",
8073
+ providers,
8074
+ accounts: state.accounts,
8075
+ chains: state.chains,
8076
+ defaults: null
8077
+ });
8078
+ } catch (err) {
8079
+ if (!cancelled) {
8080
+ captureException(err);
8081
+ }
8082
+ }
8083
+ };
8084
+ loadProviders();
8085
+ return () => {
8086
+ cancelled = true;
8087
+ };
8088
+ }, [authenticated, state.step, state.providers.length, apiBaseUrl]);
7994
8089
  react.useEffect(() => {
7995
8090
  if (!polling.transfer) return;
7996
8091
  if (polling.transfer.status === "COMPLETED") {
@@ -8246,6 +8341,77 @@ function usePaymentEffects(deps) {
8246
8341
  preOneTapSetupStepRef.current = null;
8247
8342
  }
8248
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
+ ]);
8249
8415
  }
8250
8416
  function BlinkPayment(props) {
8251
8417
  const resetKey = react.useRef(0);
@@ -8296,7 +8462,8 @@ function BlinkPaymentInner({
8296
8462
  apiBaseUrl,
8297
8463
  state.accounts,
8298
8464
  state.knownCredentialIds,
8299
- mobileFlowRefs.mobileSetupFlowRef
8465
+ mobileFlowRefs.mobileSetupFlowRef,
8466
+ state.guestPreauthAccountId
8300
8467
  );
8301
8468
  const transfer = useTransferHandlers({
8302
8469
  dispatch,
@@ -8472,7 +8639,8 @@ function BlinkPaymentInner({
8472
8639
  onSelectAuthorizedToken: provider.handleSelectAuthorizedToken,
8473
8640
  onAuthorizeToken: provider.handleAuthorizeToken,
8474
8641
  onSelectGuestToken: guestTransfer.handleSelectGuestToken,
8475
- onLogin: () => dispatch({ type: "NAVIGATE", step: "login" })
8642
+ onLogin: () => dispatch({ type: "NAVIGATE", step: "login" }),
8643
+ onPreauthorize: () => dispatch({ type: "NAVIGATE", step: "login" })
8476
8644
  }), [
8477
8645
  auth,
8478
8646
  passkey,