@swype-org/react-sdk 0.1.85 → 0.1.87
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 +49 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +49 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -189,11 +189,13 @@ interface UserConfig {
|
|
|
189
189
|
passkey?: {
|
|
190
190
|
credentialId: string;
|
|
191
191
|
publicKey: string;
|
|
192
|
+
lastVerificationToken?: string | null;
|
|
192
193
|
} | null;
|
|
193
194
|
/** All registered WebAuthn passkey credentials for this user */
|
|
194
195
|
passkeys?: {
|
|
195
196
|
credentialId: string;
|
|
196
197
|
publicKey: string;
|
|
198
|
+
lastVerificationToken?: string | null;
|
|
197
199
|
}[];
|
|
198
200
|
}
|
|
199
201
|
/** Theme mode */
|
|
@@ -321,6 +323,13 @@ declare function fetchAuthorizationSession(apiBaseUrl: string, sessionId: string
|
|
|
321
323
|
* POST /v1/users/config/passkey
|
|
322
324
|
*/
|
|
323
325
|
declare function registerPasskey(apiBaseUrl: string, token: string, credentialId: string, publicKey: string): Promise<void>;
|
|
326
|
+
/**
|
|
327
|
+
* Reports passkey activity (verification) to update the last_active
|
|
328
|
+
* timestamp server-side. Fire-and-forget — callers should not block on
|
|
329
|
+
* the result.
|
|
330
|
+
* PATCH /v1/users/config/passkey
|
|
331
|
+
*/
|
|
332
|
+
declare function reportPasskeyActivity(apiBaseUrl: string, token: string, credentialId: string): Promise<void>;
|
|
324
333
|
/**
|
|
325
334
|
* Fetches the authenticated user's config, including passkey status.
|
|
326
335
|
* GET /v1/users/config
|
|
@@ -355,11 +364,12 @@ declare const api_fetchTransfer: typeof fetchTransfer;
|
|
|
355
364
|
declare const api_fetchUserConfig: typeof fetchUserConfig;
|
|
356
365
|
declare const api_registerPasskey: typeof registerPasskey;
|
|
357
366
|
declare const api_reportActionCompletion: typeof reportActionCompletion;
|
|
367
|
+
declare const api_reportPasskeyActivity: typeof reportPasskeyActivity;
|
|
358
368
|
declare const api_signTransfer: typeof signTransfer;
|
|
359
369
|
declare const api_updateUserConfig: typeof updateUserConfig;
|
|
360
370
|
declare const api_updateUserConfigBySession: typeof updateUserConfigBySession;
|
|
361
371
|
declare namespace api {
|
|
362
|
-
export { type api_CreateTransferParams as CreateTransferParams, api_createTransfer as createTransfer, api_fetchAccounts as fetchAccounts, api_fetchAuthorizationSession as fetchAuthorizationSession, api_fetchChains as fetchChains, api_fetchMerchantPublicKey as fetchMerchantPublicKey, 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 };
|
|
372
|
+
export { type api_CreateTransferParams as CreateTransferParams, api_createTransfer as createTransfer, api_fetchAccounts as fetchAccounts, api_fetchAuthorizationSession as fetchAuthorizationSession, api_fetchChains as fetchChains, api_fetchMerchantPublicKey as fetchMerchantPublicKey, api_fetchProviders as fetchProviders, api_fetchTransfer as fetchTransfer, api_fetchUserConfig as fetchUserConfig, api_registerPasskey as registerPasskey, api_reportActionCompletion as reportActionCompletion, api_reportPasskeyActivity as reportPasskeyActivity, api_signTransfer as signTransfer, api_updateUserConfig as updateUserConfig, api_updateUserConfigBySession as updateUserConfigBySession };
|
|
363
373
|
}
|
|
364
374
|
|
|
365
375
|
interface SwypePaymentProps {
|
|
@@ -458,6 +468,12 @@ interface PasskeyVerifyPopupOptions {
|
|
|
458
468
|
rpId: string;
|
|
459
469
|
/** Populated by `findDevicePasskeyViaPopup`; not set by callers. */
|
|
460
470
|
channelId?: string;
|
|
471
|
+
/** Populated by `findDevicePasskeyViaPopup`; not set by callers. */
|
|
472
|
+
verificationToken?: string;
|
|
473
|
+
/** Privy JWT so the popup can report verification server-side. */
|
|
474
|
+
authToken?: string;
|
|
475
|
+
/** Core API base URL for server-side passkey activity reporting. */
|
|
476
|
+
apiBaseUrl?: string;
|
|
461
477
|
}
|
|
462
478
|
/**
|
|
463
479
|
* Opens a same-origin pop-up window on the Swype domain to check whether
|
|
@@ -467,6 +483,11 @@ interface PasskeyVerifyPopupOptions {
|
|
|
467
483
|
* inside a cross-origin iframe. The popup runs on the Swype domain where
|
|
468
484
|
* the rpId matches, so WebAuthn works.
|
|
469
485
|
*
|
|
486
|
+
* When `authToken` and `apiBaseUrl` are provided, the popup also writes a
|
|
487
|
+
* verification token to the backend. If Safari's ITP blocks both
|
|
488
|
+
* BroadcastChannel and window.opener.postMessage, the opener falls back to
|
|
489
|
+
* checking the server for the matching token after the popup closes.
|
|
490
|
+
*
|
|
470
491
|
* Must be called from a user-gesture handler (e.g. button click) to
|
|
471
492
|
* avoid the browser's pop-up blocker.
|
|
472
493
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -189,11 +189,13 @@ interface UserConfig {
|
|
|
189
189
|
passkey?: {
|
|
190
190
|
credentialId: string;
|
|
191
191
|
publicKey: string;
|
|
192
|
+
lastVerificationToken?: string | null;
|
|
192
193
|
} | null;
|
|
193
194
|
/** All registered WebAuthn passkey credentials for this user */
|
|
194
195
|
passkeys?: {
|
|
195
196
|
credentialId: string;
|
|
196
197
|
publicKey: string;
|
|
198
|
+
lastVerificationToken?: string | null;
|
|
197
199
|
}[];
|
|
198
200
|
}
|
|
199
201
|
/** Theme mode */
|
|
@@ -321,6 +323,13 @@ declare function fetchAuthorizationSession(apiBaseUrl: string, sessionId: string
|
|
|
321
323
|
* POST /v1/users/config/passkey
|
|
322
324
|
*/
|
|
323
325
|
declare function registerPasskey(apiBaseUrl: string, token: string, credentialId: string, publicKey: string): Promise<void>;
|
|
326
|
+
/**
|
|
327
|
+
* Reports passkey activity (verification) to update the last_active
|
|
328
|
+
* timestamp server-side. Fire-and-forget — callers should not block on
|
|
329
|
+
* the result.
|
|
330
|
+
* PATCH /v1/users/config/passkey
|
|
331
|
+
*/
|
|
332
|
+
declare function reportPasskeyActivity(apiBaseUrl: string, token: string, credentialId: string): Promise<void>;
|
|
324
333
|
/**
|
|
325
334
|
* Fetches the authenticated user's config, including passkey status.
|
|
326
335
|
* GET /v1/users/config
|
|
@@ -355,11 +364,12 @@ declare const api_fetchTransfer: typeof fetchTransfer;
|
|
|
355
364
|
declare const api_fetchUserConfig: typeof fetchUserConfig;
|
|
356
365
|
declare const api_registerPasskey: typeof registerPasskey;
|
|
357
366
|
declare const api_reportActionCompletion: typeof reportActionCompletion;
|
|
367
|
+
declare const api_reportPasskeyActivity: typeof reportPasskeyActivity;
|
|
358
368
|
declare const api_signTransfer: typeof signTransfer;
|
|
359
369
|
declare const api_updateUserConfig: typeof updateUserConfig;
|
|
360
370
|
declare const api_updateUserConfigBySession: typeof updateUserConfigBySession;
|
|
361
371
|
declare namespace api {
|
|
362
|
-
export { type api_CreateTransferParams as CreateTransferParams, api_createTransfer as createTransfer, api_fetchAccounts as fetchAccounts, api_fetchAuthorizationSession as fetchAuthorizationSession, api_fetchChains as fetchChains, api_fetchMerchantPublicKey as fetchMerchantPublicKey, 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 };
|
|
372
|
+
export { type api_CreateTransferParams as CreateTransferParams, api_createTransfer as createTransfer, api_fetchAccounts as fetchAccounts, api_fetchAuthorizationSession as fetchAuthorizationSession, api_fetchChains as fetchChains, api_fetchMerchantPublicKey as fetchMerchantPublicKey, api_fetchProviders as fetchProviders, api_fetchTransfer as fetchTransfer, api_fetchUserConfig as fetchUserConfig, api_registerPasskey as registerPasskey, api_reportActionCompletion as reportActionCompletion, api_reportPasskeyActivity as reportPasskeyActivity, api_signTransfer as signTransfer, api_updateUserConfig as updateUserConfig, api_updateUserConfigBySession as updateUserConfigBySession };
|
|
363
373
|
}
|
|
364
374
|
|
|
365
375
|
interface SwypePaymentProps {
|
|
@@ -458,6 +468,12 @@ interface PasskeyVerifyPopupOptions {
|
|
|
458
468
|
rpId: string;
|
|
459
469
|
/** Populated by `findDevicePasskeyViaPopup`; not set by callers. */
|
|
460
470
|
channelId?: string;
|
|
471
|
+
/** Populated by `findDevicePasskeyViaPopup`; not set by callers. */
|
|
472
|
+
verificationToken?: string;
|
|
473
|
+
/** Privy JWT so the popup can report verification server-side. */
|
|
474
|
+
authToken?: string;
|
|
475
|
+
/** Core API base URL for server-side passkey activity reporting. */
|
|
476
|
+
apiBaseUrl?: string;
|
|
461
477
|
}
|
|
462
478
|
/**
|
|
463
479
|
* Opens a same-origin pop-up window on the Swype domain to check whether
|
|
@@ -467,6 +483,11 @@ interface PasskeyVerifyPopupOptions {
|
|
|
467
483
|
* inside a cross-origin iframe. The popup runs on the Swype domain where
|
|
468
484
|
* the rpId matches, so WebAuthn works.
|
|
469
485
|
*
|
|
486
|
+
* When `authToken` and `apiBaseUrl` are provided, the popup also writes a
|
|
487
|
+
* verification token to the backend. If Safari's ITP blocks both
|
|
488
|
+
* BroadcastChannel and window.opener.postMessage, the opener falls back to
|
|
489
|
+
* checking the server for the matching token after the popup closes.
|
|
490
|
+
*
|
|
470
491
|
* Must be called from a user-gesture handler (e.g. button click) to
|
|
471
492
|
* avoid the browser's pop-up blocker.
|
|
472
493
|
*
|
package/dist/index.js
CHANGED
|
@@ -164,6 +164,7 @@ __export(api_exports, {
|
|
|
164
164
|
fetchUserConfig: () => fetchUserConfig,
|
|
165
165
|
registerPasskey: () => registerPasskey,
|
|
166
166
|
reportActionCompletion: () => reportActionCompletion,
|
|
167
|
+
reportPasskeyActivity: () => reportPasskeyActivity,
|
|
167
168
|
signTransfer: () => signTransfer,
|
|
168
169
|
updateUserConfig: () => updateUserConfig,
|
|
169
170
|
updateUserConfigBySession: () => updateUserConfigBySession
|
|
@@ -286,6 +287,17 @@ async function registerPasskey(apiBaseUrl, token, credentialId, publicKey) {
|
|
|
286
287
|
});
|
|
287
288
|
if (!res.ok) await throwApiError(res);
|
|
288
289
|
}
|
|
290
|
+
async function reportPasskeyActivity(apiBaseUrl, token, credentialId) {
|
|
291
|
+
const res = await fetch(`${apiBaseUrl}/v1/users/config/passkey`, {
|
|
292
|
+
method: "PATCH",
|
|
293
|
+
headers: {
|
|
294
|
+
"Content-Type": "application/json",
|
|
295
|
+
Authorization: `Bearer ${token}`
|
|
296
|
+
},
|
|
297
|
+
body: JSON.stringify({ credentialId })
|
|
298
|
+
});
|
|
299
|
+
if (!res.ok) await throwApiError(res);
|
|
300
|
+
}
|
|
289
301
|
async function fetchUserConfig(apiBaseUrl, token) {
|
|
290
302
|
const res = await fetch(`${apiBaseUrl}/v1/users/config`, {
|
|
291
303
|
headers: { Authorization: `Bearer ${token}` }
|
|
@@ -789,7 +801,12 @@ var VERIFY_POPUP_TIMEOUT_MS = 6e4;
|
|
|
789
801
|
function findDevicePasskeyViaPopup(options) {
|
|
790
802
|
return new Promise((resolve, reject) => {
|
|
791
803
|
const channelId = `swype-pv-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
792
|
-
const
|
|
804
|
+
const verificationToken = crypto.randomUUID();
|
|
805
|
+
const payload = {
|
|
806
|
+
...options,
|
|
807
|
+
channelId,
|
|
808
|
+
verificationToken
|
|
809
|
+
};
|
|
793
810
|
const encoded = btoa(JSON.stringify(payload));
|
|
794
811
|
const popupUrl = `${window.location.origin}/passkey-verify#${encoded}`;
|
|
795
812
|
const popup = window.open(popupUrl, "swype-passkey-verify");
|
|
@@ -809,7 +826,15 @@ function findDevicePasskeyViaPopup(options) {
|
|
|
809
826
|
setTimeout(() => {
|
|
810
827
|
if (!settled) {
|
|
811
828
|
cleanup();
|
|
812
|
-
|
|
829
|
+
checkServerForVerifiedPasskey(
|
|
830
|
+
options.authToken,
|
|
831
|
+
options.apiBaseUrl,
|
|
832
|
+
verificationToken
|
|
833
|
+
).then((credentialId) => {
|
|
834
|
+
resolve(credentialId);
|
|
835
|
+
}).catch(() => {
|
|
836
|
+
resolve(null);
|
|
837
|
+
});
|
|
813
838
|
}
|
|
814
839
|
}, POPUP_CLOSED_GRACE_MS);
|
|
815
840
|
}
|
|
@@ -845,6 +870,17 @@ function findDevicePasskeyViaPopup(options) {
|
|
|
845
870
|
}
|
|
846
871
|
});
|
|
847
872
|
}
|
|
873
|
+
async function checkServerForVerifiedPasskey(authToken, apiBaseUrl, verificationToken) {
|
|
874
|
+
if (!authToken || !apiBaseUrl) return null;
|
|
875
|
+
const res = await fetch(`${apiBaseUrl}/v1/users/config`, {
|
|
876
|
+
headers: { Authorization: `Bearer ${authToken}` }
|
|
877
|
+
});
|
|
878
|
+
if (!res.ok) return null;
|
|
879
|
+
const body = await res.json();
|
|
880
|
+
const passkeys = body.config.passkeys ?? [];
|
|
881
|
+
const matched = passkeys.find((p) => p.lastVerificationToken === verificationToken);
|
|
882
|
+
return matched?.credentialId ?? null;
|
|
883
|
+
}
|
|
848
884
|
async function checkServerForNewPasskey(authToken, apiBaseUrl, existingCredentialIds) {
|
|
849
885
|
if (!authToken || !apiBaseUrl) return null;
|
|
850
886
|
const res = await fetch(`${apiBaseUrl}/v1/users/config`, {
|
|
@@ -5049,6 +5085,8 @@ function SwypePaymentInner({
|
|
|
5049
5085
|
if (matched) {
|
|
5050
5086
|
setActiveCredentialId(matched);
|
|
5051
5087
|
window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
|
|
5088
|
+
reportPasskeyActivity(apiBaseUrl, token, matched).catch(() => {
|
|
5089
|
+
});
|
|
5052
5090
|
await restoreOrDeposit(matched, token);
|
|
5053
5091
|
return;
|
|
5054
5092
|
}
|
|
@@ -5574,13 +5612,20 @@ function SwypePaymentInner({
|
|
|
5574
5612
|
setVerifyingPasskeyPopup(true);
|
|
5575
5613
|
setError(null);
|
|
5576
5614
|
try {
|
|
5615
|
+
const token = await getAccessToken();
|
|
5577
5616
|
const matched = await findDevicePasskeyViaPopup({
|
|
5578
5617
|
credentialIds: knownCredentialIds,
|
|
5579
|
-
rpId: resolvePasskeyRpId()
|
|
5618
|
+
rpId: resolvePasskeyRpId(),
|
|
5619
|
+
authToken: token ?? void 0,
|
|
5620
|
+
apiBaseUrl
|
|
5580
5621
|
});
|
|
5581
5622
|
if (matched) {
|
|
5582
5623
|
setActiveCredentialId(matched);
|
|
5583
5624
|
window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
|
|
5625
|
+
if (token) {
|
|
5626
|
+
reportPasskeyActivity(apiBaseUrl, token, matched).catch(() => {
|
|
5627
|
+
});
|
|
5628
|
+
}
|
|
5584
5629
|
setStep("login");
|
|
5585
5630
|
} else {
|
|
5586
5631
|
setStep("create-passkey");
|
|
@@ -5590,7 +5635,7 @@ function SwypePaymentInner({
|
|
|
5590
5635
|
} finally {
|
|
5591
5636
|
setVerifyingPasskeyPopup(false);
|
|
5592
5637
|
}
|
|
5593
|
-
}, [knownCredentialIds]);
|
|
5638
|
+
}, [knownCredentialIds, getAccessToken, apiBaseUrl]);
|
|
5594
5639
|
const handleSelectProvider = useCallback((providerId) => {
|
|
5595
5640
|
setSelectedProviderId(providerId);
|
|
5596
5641
|
setSelectedAccountId(null);
|