@swype-org/react-sdk 0.1.27 → 0.1.28

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.d.cts CHANGED
@@ -297,8 +297,16 @@ interface SwypePaymentProps {
297
297
  * wallet extensions are unavailable.
298
298
  */
299
299
  useWalletConnector?: boolean;
300
+ /**
301
+ * Caller-supplied UUID v4 used as the transfer ID for idempotency.
302
+ *
303
+ * When provided, the transfer is created with this ID instead of a
304
+ * randomly generated one. This allows callers to safely retry the payment
305
+ * flow without creating duplicate transfers.
306
+ */
307
+ idempotencyKey?: string;
300
308
  }
301
- declare function SwypePayment({ destination, onComplete, onError, useWalletConnector, }: SwypePaymentProps): react_jsx_runtime.JSX.Element | null;
309
+ declare function SwypePayment({ destination, onComplete, onError, useWalletConnector, idempotencyKey, }: SwypePaymentProps): react_jsx_runtime.JSX.Element | null;
302
310
 
303
311
  type AccessTokenGetter = () => Promise<string | null | undefined>;
304
312
  /**
@@ -320,17 +328,20 @@ declare function createPasskeyCredential(params: {
320
328
  publicKey: string;
321
329
  }>;
322
330
  /**
323
- * Checks whether the current device's platform authenticator holds a passkey
324
- * matching the given credential ID.
325
- *
326
- * Uses `navigator.credentials.get()` with a throwaway challenge and a short
327
- * timeout. If the authenticator responds, the device has the key. If it
328
- * throws (NotAllowedError, timeout, etc.), the device does not.
329
- *
330
- * @param credentialId - Base64-encoded WebAuthn credential ID from the server.
331
- * @returns `true` if the device can authenticate with this credential.
331
+ * @deprecated Use {@link findDevicePasskey} instead, which checks all
332
+ * credentials in a single WebAuthn call.
332
333
  */
333
334
  declare function deviceHasPasskey(credentialId: string): Promise<boolean>;
335
+ /**
336
+ * Determines which (if any) of the given server-registered passkeys exists on
337
+ * the current device. All credential IDs are passed in a single
338
+ * `navigator.credentials.get()` call so the browser shows at most one prompt
339
+ * and the platform authenticator automatically selects the matching key.
340
+ *
341
+ * @param credentialIds - Base64-encoded WebAuthn credential IDs from the server.
342
+ * @returns The matching credential ID, or `null` if none are on this device.
343
+ */
344
+ declare function findDevicePasskey(credentialIds: string[]): Promise<string | null>;
334
345
  interface UseTransferPollingResult {
335
346
  transfer: Transfer | null;
336
347
  error: string | null;
@@ -413,6 +424,8 @@ declare function fetchProviders(apiBaseUrl: string, token: string): Promise<Prov
413
424
  declare function fetchChains(apiBaseUrl: string, token: string): Promise<Chain[]>;
414
425
  declare function fetchAccounts(apiBaseUrl: string, token: string, credentialId: string): Promise<Account[]>;
415
426
  interface CreateTransferParams {
427
+ /** Caller-supplied UUID v4 for idempotency. If omitted, a random UUID is generated. */
428
+ id?: string;
416
429
  credentialId: string;
417
430
  sourceType: SourceType;
418
431
  sourceId: string;
@@ -473,4 +486,4 @@ declare namespace api {
473
486
  export { type api_CreateTransferParams as CreateTransferParams, api_createTransfer as createTransfer, api_fetchAccounts as fetchAccounts, api_fetchAuthorizationSession as fetchAuthorizationSession, api_fetchChains as fetchChains, api_fetchProviders as fetchProviders, api_fetchTransfer as fetchTransfer, api_fetchUserConfig as fetchUserConfig, api_registerPasskey as registerPasskey, api_reportActionCompletion as reportActionCompletion, api_signTransfer as signTransfer, api_updateUserConfig as updateUserConfig, api_updateUserConfigBySession as updateUserConfigBySession };
474
487
  }
475
488
 
476
- export { type Account, type ActionExecutionResult, type AdvancedSettings, type Amount, type AuthorizationAction, type AuthorizationSession, type AuthorizationSessionDetail, type Chain, type Destination, type ErrorResponse, type ListResponse, type PaymentStep, type Provider, type SourceOption, type SourceSelection, type SourceType, SwypePayment, type SwypePaymentProps, SwypeProvider, type SwypeProviderProps, type ThemeMode, type ThemeTokens, type TokenBalance, type Transfer, type TransferDestination, type UserConfig, type Wallet, type WalletSource, type WalletToken, createPasskeyCredential, darkTheme, deviceHasPasskey, getTheme, lightTheme, api as swypeApi, useAuthorizationExecutor, useSwypeConfig, useSwypeDepositAmount, useTransferPolling, useTransferSigning };
489
+ export { type Account, type ActionExecutionResult, type AdvancedSettings, type Amount, type AuthorizationAction, type AuthorizationSession, type AuthorizationSessionDetail, type Chain, type Destination, type ErrorResponse, type ListResponse, type PaymentStep, type Provider, type SourceOption, type SourceSelection, type SourceType, SwypePayment, type SwypePaymentProps, SwypeProvider, type SwypeProviderProps, type ThemeMode, type ThemeTokens, type TokenBalance, type Transfer, type TransferDestination, type UserConfig, type Wallet, type WalletSource, type WalletToken, createPasskeyCredential, darkTheme, deviceHasPasskey, findDevicePasskey, getTheme, lightTheme, api as swypeApi, useAuthorizationExecutor, useSwypeConfig, useSwypeDepositAmount, useTransferPolling, useTransferSigning };
package/dist/index.d.ts CHANGED
@@ -297,8 +297,16 @@ interface SwypePaymentProps {
297
297
  * wallet extensions are unavailable.
298
298
  */
299
299
  useWalletConnector?: boolean;
300
+ /**
301
+ * Caller-supplied UUID v4 used as the transfer ID for idempotency.
302
+ *
303
+ * When provided, the transfer is created with this ID instead of a
304
+ * randomly generated one. This allows callers to safely retry the payment
305
+ * flow without creating duplicate transfers.
306
+ */
307
+ idempotencyKey?: string;
300
308
  }
301
- declare function SwypePayment({ destination, onComplete, onError, useWalletConnector, }: SwypePaymentProps): react_jsx_runtime.JSX.Element | null;
309
+ declare function SwypePayment({ destination, onComplete, onError, useWalletConnector, idempotencyKey, }: SwypePaymentProps): react_jsx_runtime.JSX.Element | null;
302
310
 
303
311
  type AccessTokenGetter = () => Promise<string | null | undefined>;
304
312
  /**
@@ -320,17 +328,20 @@ declare function createPasskeyCredential(params: {
320
328
  publicKey: string;
321
329
  }>;
322
330
  /**
323
- * Checks whether the current device's platform authenticator holds a passkey
324
- * matching the given credential ID.
325
- *
326
- * Uses `navigator.credentials.get()` with a throwaway challenge and a short
327
- * timeout. If the authenticator responds, the device has the key. If it
328
- * throws (NotAllowedError, timeout, etc.), the device does not.
329
- *
330
- * @param credentialId - Base64-encoded WebAuthn credential ID from the server.
331
- * @returns `true` if the device can authenticate with this credential.
331
+ * @deprecated Use {@link findDevicePasskey} instead, which checks all
332
+ * credentials in a single WebAuthn call.
332
333
  */
333
334
  declare function deviceHasPasskey(credentialId: string): Promise<boolean>;
335
+ /**
336
+ * Determines which (if any) of the given server-registered passkeys exists on
337
+ * the current device. All credential IDs are passed in a single
338
+ * `navigator.credentials.get()` call so the browser shows at most one prompt
339
+ * and the platform authenticator automatically selects the matching key.
340
+ *
341
+ * @param credentialIds - Base64-encoded WebAuthn credential IDs from the server.
342
+ * @returns The matching credential ID, or `null` if none are on this device.
343
+ */
344
+ declare function findDevicePasskey(credentialIds: string[]): Promise<string | null>;
334
345
  interface UseTransferPollingResult {
335
346
  transfer: Transfer | null;
336
347
  error: string | null;
@@ -413,6 +424,8 @@ declare function fetchProviders(apiBaseUrl: string, token: string): Promise<Prov
413
424
  declare function fetchChains(apiBaseUrl: string, token: string): Promise<Chain[]>;
414
425
  declare function fetchAccounts(apiBaseUrl: string, token: string, credentialId: string): Promise<Account[]>;
415
426
  interface CreateTransferParams {
427
+ /** Caller-supplied UUID v4 for idempotency. If omitted, a random UUID is generated. */
428
+ id?: string;
416
429
  credentialId: string;
417
430
  sourceType: SourceType;
418
431
  sourceId: string;
@@ -473,4 +486,4 @@ declare namespace api {
473
486
  export { type api_CreateTransferParams as CreateTransferParams, api_createTransfer as createTransfer, api_fetchAccounts as fetchAccounts, api_fetchAuthorizationSession as fetchAuthorizationSession, api_fetchChains as fetchChains, api_fetchProviders as fetchProviders, api_fetchTransfer as fetchTransfer, api_fetchUserConfig as fetchUserConfig, api_registerPasskey as registerPasskey, api_reportActionCompletion as reportActionCompletion, api_signTransfer as signTransfer, api_updateUserConfig as updateUserConfig, api_updateUserConfigBySession as updateUserConfigBySession };
474
487
  }
475
488
 
476
- export { type Account, type ActionExecutionResult, type AdvancedSettings, type Amount, type AuthorizationAction, type AuthorizationSession, type AuthorizationSessionDetail, type Chain, type Destination, type ErrorResponse, type ListResponse, type PaymentStep, type Provider, type SourceOption, type SourceSelection, type SourceType, SwypePayment, type SwypePaymentProps, SwypeProvider, type SwypeProviderProps, type ThemeMode, type ThemeTokens, type TokenBalance, type Transfer, type TransferDestination, type UserConfig, type Wallet, type WalletSource, type WalletToken, createPasskeyCredential, darkTheme, deviceHasPasskey, getTheme, lightTheme, api as swypeApi, useAuthorizationExecutor, useSwypeConfig, useSwypeDepositAmount, useTransferPolling, useTransferSigning };
489
+ export { type Account, type ActionExecutionResult, type AdvancedSettings, type Amount, type AuthorizationAction, type AuthorizationSession, type AuthorizationSessionDetail, type Chain, type Destination, type ErrorResponse, type ListResponse, type PaymentStep, type Provider, type SourceOption, type SourceSelection, type SourceType, SwypePayment, type SwypePaymentProps, SwypeProvider, type SwypeProviderProps, type ThemeMode, type ThemeTokens, type TokenBalance, type Transfer, type TransferDestination, type UserConfig, type Wallet, type WalletSource, type WalletToken, createPasskeyCredential, darkTheme, deviceHasPasskey, findDevicePasskey, getTheme, lightTheme, api as swypeApi, useAuthorizationExecutor, useSwypeConfig, useSwypeDepositAmount, useTransferPolling, useTransferSigning };
package/dist/index.js CHANGED
@@ -216,7 +216,7 @@ async function fetchAccounts(apiBaseUrl, token, credentialId) {
216
216
  }
217
217
  async function createTransfer(apiBaseUrl, token, params) {
218
218
  const body = {
219
- id: crypto.randomUUID(),
219
+ id: params.id ?? crypto.randomUUID(),
220
220
  credentialId: params.credentialId,
221
221
  sources: [{ [params.sourceType]: params.sourceId }],
222
222
  destinations: [
@@ -813,6 +813,11 @@ async function createPasskeyCredential(params) {
813
813
  };
814
814
  }
815
815
  async function deviceHasPasskey(credentialId) {
816
+ const found = await findDevicePasskey([credentialId]);
817
+ return found != null;
818
+ }
819
+ async function findDevicePasskey(credentialIds) {
820
+ if (credentialIds.length === 0) return null;
816
821
  try {
817
822
  const challenge = new Uint8Array(32);
818
823
  crypto.getRandomValues(challenge);
@@ -821,17 +826,18 @@ async function deviceHasPasskey(credentialId) {
821
826
  publicKey: {
822
827
  challenge,
823
828
  rpId: resolvePasskeyRpId(),
824
- allowCredentials: [{
829
+ allowCredentials: credentialIds.map((id) => ({
825
830
  type: "public-key",
826
- id: base64ToBytes(credentialId)
827
- }],
831
+ id: base64ToBytes(id)
832
+ })),
828
833
  userVerification: "discouraged",
829
834
  timeout: 3e4
830
835
  }
831
836
  });
832
- return assertion != null;
837
+ if (!assertion) return null;
838
+ return toBase64(assertion.rawId);
833
839
  } catch {
834
- return false;
840
+ return null;
835
841
  }
836
842
  }
837
843
  function useTransferPolling(intervalMs = 3e3) {
@@ -2196,7 +2202,8 @@ function SwypePayment({
2196
2202
  destination,
2197
2203
  onComplete,
2198
2204
  onError,
2199
- useWalletConnector
2205
+ useWalletConnector,
2206
+ idempotencyKey
2200
2207
  }) {
2201
2208
  const { apiBaseUrl, tokens, depositAmount } = useSwypeConfig();
2202
2209
  const { ready, authenticated, user, login, logout, getAccessToken } = usePrivy();
@@ -2263,20 +2270,20 @@ function SwypePayment({
2263
2270
  }
2264
2271
  return;
2265
2272
  }
2266
- for (const pk of allPasskeys) {
2267
- if (cancelled) return;
2268
- if (await deviceHasPasskey(pk.credentialId)) {
2269
- setActiveCredentialId(pk.credentialId);
2270
- window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, pk.credentialId);
2271
- if (depositAmount != null && depositAmount > 0) {
2272
- setStep("ready");
2273
- } else {
2274
- setStep("enter-amount");
2275
- }
2276
- return;
2273
+ if (cancelled) return;
2274
+ const credentialIds = allPasskeys.map((p) => p.credentialId);
2275
+ const matched = await findDevicePasskey(credentialIds);
2276
+ if (cancelled) return;
2277
+ if (matched) {
2278
+ setActiveCredentialId(matched);
2279
+ window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
2280
+ if (depositAmount != null && depositAmount > 0) {
2281
+ setStep("ready");
2282
+ } else {
2283
+ setStep("enter-amount");
2277
2284
  }
2285
+ return;
2278
2286
  }
2279
- if (cancelled) return;
2280
2287
  setStep("register-passkey");
2281
2288
  } catch {
2282
2289
  if (!cancelled) {
@@ -2510,6 +2517,7 @@ function SwypePayment({
2510
2517
  }
2511
2518
  }
2512
2519
  const t = await createTransfer(apiBaseUrl, token, {
2520
+ id: idempotencyKey,
2513
2521
  credentialId: activeCredentialId,
2514
2522
  sourceType: effectiveSourceType,
2515
2523
  sourceId: effectiveSourceId,
@@ -3543,6 +3551,6 @@ function SwypePayment({
3543
3551
  return null;
3544
3552
  }
3545
3553
 
3546
- export { SwypePayment, SwypeProvider, createPasskeyCredential, darkTheme, deviceHasPasskey, getTheme, lightTheme, api_exports as swypeApi, useAuthorizationExecutor, useSwypeConfig, useSwypeDepositAmount, useTransferPolling, useTransferSigning };
3554
+ export { SwypePayment, SwypeProvider, createPasskeyCredential, darkTheme, deviceHasPasskey, findDevicePasskey, getTheme, lightTheme, api_exports as swypeApi, useAuthorizationExecutor, useSwypeConfig, useSwypeDepositAmount, useTransferPolling, useTransferSigning };
3547
3555
  //# sourceMappingURL=index.js.map
3548
3556
  //# sourceMappingURL=index.js.map