@swype-org/react-sdk 0.1.14 → 0.1.16
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 +73 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +73 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -591,6 +591,28 @@ var ACTION_POLL_MAX_RETRIES = 20;
|
|
|
591
591
|
var SIGN_PERMIT2_POLL_MS = 1e3;
|
|
592
592
|
var SIGN_PERMIT2_MAX_POLLS = 15;
|
|
593
593
|
var TRANSFER_SIGN_MAX_POLLS = 60;
|
|
594
|
+
function waitForDocumentFocus(timeoutMs = 5e3, intervalMs = 100) {
|
|
595
|
+
return new Promise((resolve, reject) => {
|
|
596
|
+
if (typeof document === "undefined") {
|
|
597
|
+
resolve();
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
if (document.hasFocus()) {
|
|
601
|
+
resolve();
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
const deadline = Date.now() + timeoutMs;
|
|
605
|
+
const timer = setInterval(() => {
|
|
606
|
+
if (document.hasFocus()) {
|
|
607
|
+
clearInterval(timer);
|
|
608
|
+
resolve();
|
|
609
|
+
} else if (Date.now() >= deadline) {
|
|
610
|
+
clearInterval(timer);
|
|
611
|
+
resolve();
|
|
612
|
+
}
|
|
613
|
+
}, intervalMs);
|
|
614
|
+
});
|
|
615
|
+
}
|
|
594
616
|
function actionSuccess(action, message, data) {
|
|
595
617
|
return { actionId: action.id, type: action.type, status: "success", message, data };
|
|
596
618
|
}
|
|
@@ -682,6 +704,7 @@ async function createPasskeyCredential(userIdentifier) {
|
|
|
682
704
|
const challenge = new Uint8Array(32);
|
|
683
705
|
crypto.getRandomValues(challenge);
|
|
684
706
|
const rpId = resolvePasskeyRpId();
|
|
707
|
+
await waitForDocumentFocus();
|
|
685
708
|
const credential = await navigator.credentials.create({
|
|
686
709
|
publicKey: {
|
|
687
710
|
challenge,
|
|
@@ -715,6 +738,28 @@ async function createPasskeyCredential(userIdentifier) {
|
|
|
715
738
|
publicKey: publicKeyBytes ? toBase64(publicKeyBytes) : ""
|
|
716
739
|
};
|
|
717
740
|
}
|
|
741
|
+
async function deviceHasPasskey(credentialId) {
|
|
742
|
+
try {
|
|
743
|
+
const challenge = new Uint8Array(32);
|
|
744
|
+
crypto.getRandomValues(challenge);
|
|
745
|
+
await waitForDocumentFocus();
|
|
746
|
+
const assertion = await navigator.credentials.get({
|
|
747
|
+
publicKey: {
|
|
748
|
+
challenge,
|
|
749
|
+
rpId: resolvePasskeyRpId(),
|
|
750
|
+
allowCredentials: [{
|
|
751
|
+
type: "public-key",
|
|
752
|
+
id: base64ToBytes(credentialId)
|
|
753
|
+
}],
|
|
754
|
+
userVerification: "required",
|
|
755
|
+
timeout: 3e4
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
return assertion != null;
|
|
759
|
+
} catch {
|
|
760
|
+
return false;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
718
763
|
function useTransferPolling(intervalMs = 3e3) {
|
|
719
764
|
const { apiBaseUrl } = useSwypeConfig();
|
|
720
765
|
const { getAccessToken } = reactAuth.usePrivy();
|
|
@@ -1187,6 +1232,7 @@ function useTransferSigning(pollIntervalMs = 2e3, options) {
|
|
|
1187
1232
|
type: "public-key",
|
|
1188
1233
|
id: base64ToBytes(payload.passkeyCredentialId)
|
|
1189
1234
|
}] : void 0;
|
|
1235
|
+
await waitForDocumentFocus();
|
|
1190
1236
|
const assertion = await navigator.credentials.get({
|
|
1191
1237
|
publicKey: {
|
|
1192
1238
|
challenge: hashBytes,
|
|
@@ -1983,6 +2029,7 @@ function buildProcessingTimeoutMessage(status) {
|
|
|
1983
2029
|
return `Payment is taking longer than expected (status: ${status}). Please try again.`;
|
|
1984
2030
|
}
|
|
1985
2031
|
var ACTIVE_CREDENTIAL_STORAGE_KEY = "swype_active_credential_id";
|
|
2032
|
+
var MIN_SEND_AMOUNT_USD = 0.25;
|
|
1986
2033
|
function isMobile() {
|
|
1987
2034
|
if (typeof navigator === "undefined") return false;
|
|
1988
2035
|
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
@@ -2116,12 +2163,27 @@ function SwypePayment({
|
|
|
2116
2163
|
if (!token || cancelled) return;
|
|
2117
2164
|
const { config } = await fetchUserConfig(apiBaseUrl, token);
|
|
2118
2165
|
if (cancelled) return;
|
|
2119
|
-
if (
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2166
|
+
if (config.passkey?.credentialId) {
|
|
2167
|
+
const hasKey = activeCredentialId ? activeCredentialId === config.passkey.credentialId : await deviceHasPasskey(config.passkey.credentialId);
|
|
2168
|
+
if (cancelled) return;
|
|
2169
|
+
if (hasKey) {
|
|
2170
|
+
if (!activeCredentialId) {
|
|
2171
|
+
setActiveCredentialId(config.passkey.credentialId);
|
|
2172
|
+
window.localStorage.setItem(
|
|
2173
|
+
ACTIVE_CREDENTIAL_STORAGE_KEY,
|
|
2174
|
+
config.passkey.credentialId
|
|
2175
|
+
);
|
|
2176
|
+
}
|
|
2177
|
+
if (depositAmount != null && depositAmount > 0) {
|
|
2178
|
+
setStep("ready");
|
|
2179
|
+
} else {
|
|
2180
|
+
setStep("enter-amount");
|
|
2181
|
+
}
|
|
2182
|
+
} else {
|
|
2183
|
+
setStep("register-passkey");
|
|
2184
|
+
}
|
|
2123
2185
|
} else {
|
|
2124
|
-
setStep("
|
|
2186
|
+
setStep("register-passkey");
|
|
2125
2187
|
}
|
|
2126
2188
|
} catch {
|
|
2127
2189
|
if (!cancelled) {
|
|
@@ -2308,8 +2370,8 @@ function SwypePayment({
|
|
|
2308
2370
|
}, [pendingSelectSourceAction, selectSourceChoices, selectSourceRecommended]);
|
|
2309
2371
|
const handlePay = react.useCallback(async () => {
|
|
2310
2372
|
const parsedAmount = parseFloat(amount);
|
|
2311
|
-
if (isNaN(parsedAmount) || parsedAmount
|
|
2312
|
-
setError(
|
|
2373
|
+
if (isNaN(parsedAmount) || parsedAmount < MIN_SEND_AMOUNT_USD) {
|
|
2374
|
+
setError(`Minimum amount is $${MIN_SEND_AMOUNT_USD.toFixed(2)}.`);
|
|
2313
2375
|
return;
|
|
2314
2376
|
}
|
|
2315
2377
|
if (!sourceId) {
|
|
@@ -2685,7 +2747,7 @@ function SwypePayment({
|
|
|
2685
2747
|
}
|
|
2686
2748
|
if (step === "enter-amount") {
|
|
2687
2749
|
const parsedAmount = parseFloat(amount);
|
|
2688
|
-
const canContinue = !isNaN(parsedAmount) && parsedAmount
|
|
2750
|
+
const canContinue = !isNaN(parsedAmount) && parsedAmount >= MIN_SEND_AMOUNT_USD;
|
|
2689
2751
|
let maxSourceBalance = null;
|
|
2690
2752
|
for (const acct of accounts) {
|
|
2691
2753
|
for (const wallet of acct.wallets) {
|
|
@@ -2732,7 +2794,7 @@ function SwypePayment({
|
|
|
2732
2794
|
"input",
|
|
2733
2795
|
{
|
|
2734
2796
|
type: "number",
|
|
2735
|
-
min:
|
|
2797
|
+
min: MIN_SEND_AMOUNT_USD.toFixed(2),
|
|
2736
2798
|
step: "0.01",
|
|
2737
2799
|
value: amount,
|
|
2738
2800
|
onChange: (e) => setAmount(e.target.value),
|
|
@@ -2802,7 +2864,7 @@ function SwypePayment({
|
|
|
2802
2864
|
}
|
|
2803
2865
|
if (step === "ready") {
|
|
2804
2866
|
const parsedAmount = parseFloat(amount);
|
|
2805
|
-
const canPay = !isNaN(parsedAmount) && parsedAmount
|
|
2867
|
+
const canPay = !isNaN(parsedAmount) && parsedAmount >= MIN_SEND_AMOUNT_USD && !!sourceId && !loadingData;
|
|
2806
2868
|
const noAccounts = !loadingData && accounts.length === 0;
|
|
2807
2869
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardStyle, children: [
|
|
2808
2870
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
|
|
@@ -3437,6 +3499,7 @@ exports.SwypePayment = SwypePayment;
|
|
|
3437
3499
|
exports.SwypeProvider = SwypeProvider;
|
|
3438
3500
|
exports.createPasskeyCredential = createPasskeyCredential;
|
|
3439
3501
|
exports.darkTheme = darkTheme;
|
|
3502
|
+
exports.deviceHasPasskey = deviceHasPasskey;
|
|
3440
3503
|
exports.getTheme = getTheme;
|
|
3441
3504
|
exports.lightTheme = lightTheme;
|
|
3442
3505
|
exports.swypeApi = api_exports;
|