@volr/react-ui 0.1.124 → 0.1.126
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 +192 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +193 -5
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React13, { createContext, useContext, useState, useMemo, useEffect, useCallback, useRef, useId, useReducer } from 'react';
|
|
2
2
|
import { createPortal } from 'react-dom';
|
|
3
|
-
import { useVolrContext, useInternalAuth, usePasskeyEnrollment, checkPrfCompatibility, getPlatformHint, useMpcConnection, VolrProvider, useVolrAuthCallback, useVolrPaymentApi, useUserBalances, useVolrLogin, useVolr, useWithdraw, useDepositListener, createGetNetworkInfo, useEIP6963 } from '@volr/react';
|
|
3
|
+
import { useVolrContext, useInternalAuth, usePasskeyEnrollment, checkPrfCompatibility, getPlatformHint, useMpcConnection, VolrProvider, useVolrAuthCallback, useVolrPaymentApi, completeMigration, requestMigration, decryptEntropyForMigration, listenForSeedRequests, useUserBalances, useVolrLogin, useVolr, useWithdraw, useDepositListener, createGetNetworkInfo, useEIP6963 } from '@volr/react';
|
|
4
4
|
export { VolrProvider, useDepositListener, usePasskeyEnrollment, useVolr, useVolrLogin, useVolrPaymentApi } from '@volr/react';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import { clsx } from 'clsx';
|
|
@@ -2157,7 +2157,12 @@ function PasskeyEnrollView({
|
|
|
2157
2157
|
}
|
|
2158
2158
|
if (migrationInfo.needsMigration && migrationInfo.sourcePasskey) {
|
|
2159
2159
|
const handleMigration = async () => {
|
|
2160
|
-
|
|
2160
|
+
const targetOrigin = typeof window !== "undefined" ? window.location.origin : "";
|
|
2161
|
+
const sourceRpId = migrationInfo.sourcePasskey.rpId;
|
|
2162
|
+
const sourceOrigin = sourceRpId === "localhost" ? "http://localhost" : `https://${sourceRpId}`;
|
|
2163
|
+
const url = new URL(sourceOrigin);
|
|
2164
|
+
url.searchParams.set("volr_migrate_to", targetOrigin);
|
|
2165
|
+
window.open(url.toString(), "_blank", "noopener,noreferrer");
|
|
2161
2166
|
};
|
|
2162
2167
|
return /* @__PURE__ */ jsx(
|
|
2163
2168
|
PasskeyMigrationView,
|
|
@@ -5125,6 +5130,8 @@ function AccountModal({ isOpen, onClose, onError }) {
|
|
|
5125
5130
|
const [currentView, setCurrentView] = useState("main");
|
|
5126
5131
|
const [selectedPayment, setSelectedPayment] = useState(null);
|
|
5127
5132
|
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
|
5133
|
+
const prevUserRef = useRef(user ?? null);
|
|
5134
|
+
const [closingAfterLogin, setClosingAfterLogin] = useState(false);
|
|
5128
5135
|
const [depositAssets, setDepositAssets] = useState([]);
|
|
5129
5136
|
const [depositLoading, setDepositLoading] = useState(false);
|
|
5130
5137
|
const [depositError, setDepositError] = useState(null);
|
|
@@ -5155,6 +5162,29 @@ function AccountModal({ isOpen, onClose, onError }) {
|
|
|
5155
5162
|
}, 200);
|
|
5156
5163
|
}
|
|
5157
5164
|
}, [onClose]);
|
|
5165
|
+
useEffect(() => {
|
|
5166
|
+
if (!isOpen) {
|
|
5167
|
+
setClosingAfterLogin(false);
|
|
5168
|
+
prevUserRef.current = user ?? null;
|
|
5169
|
+
return;
|
|
5170
|
+
}
|
|
5171
|
+
const wasLoggedOut = prevUserRef.current == null;
|
|
5172
|
+
const isNowLoggedIn = user != null;
|
|
5173
|
+
if (wasLoggedOut && isNowLoggedIn) {
|
|
5174
|
+
setClosingAfterLogin(true);
|
|
5175
|
+
setTimeout(() => {
|
|
5176
|
+
onClose();
|
|
5177
|
+
}, 0);
|
|
5178
|
+
}
|
|
5179
|
+
prevUserRef.current = user ?? null;
|
|
5180
|
+
}, [isOpen, user, onClose]);
|
|
5181
|
+
if (closingAfterLogin && isOpen) {
|
|
5182
|
+
return /* @__PURE__ */ jsxs(Modal, { open: isOpen, onOpenChange: handleOpenChange, children: [
|
|
5183
|
+
/* @__PURE__ */ jsx(ModalHeader, { onClose: () => {
|
|
5184
|
+
} }),
|
|
5185
|
+
/* @__PURE__ */ jsx("div", { className: "volr:text-center volr:py-8", children: /* @__PURE__ */ jsx("p", { className: "volr:text-sm volr-text-secondary", children: "Completing login..." }) })
|
|
5186
|
+
] });
|
|
5187
|
+
}
|
|
5158
5188
|
if (!user) {
|
|
5159
5189
|
return /* @__PURE__ */ jsx(SigninModal, { isOpen, onClose, onError });
|
|
5160
5190
|
}
|
|
@@ -6632,6 +6662,17 @@ function SignRequestModal({ open, onOpenChange }) {
|
|
|
6632
6662
|
);
|
|
6633
6663
|
}
|
|
6634
6664
|
var VolrUIContext = React13.createContext(null);
|
|
6665
|
+
function getCurrentRpId() {
|
|
6666
|
+
if (typeof window === "undefined") return "localhost";
|
|
6667
|
+
return window.location.hostname;
|
|
6668
|
+
}
|
|
6669
|
+
function isPasskeyDomainMismatch(user) {
|
|
6670
|
+
const currentRpId = getCurrentRpId();
|
|
6671
|
+
const registered = user?.registeredPasskeys;
|
|
6672
|
+
if (user?.keyStorageType !== "passkey") return false;
|
|
6673
|
+
if (!Array.isArray(registered) || registered.length === 0) return false;
|
|
6674
|
+
return !registered.some((p) => p?.rpId === currentRpId);
|
|
6675
|
+
}
|
|
6635
6676
|
var useVolrUI = () => {
|
|
6636
6677
|
const context = useContext(VolrUIContext);
|
|
6637
6678
|
if (!context) {
|
|
@@ -6762,6 +6803,13 @@ function VolrUIProviderInner({
|
|
|
6762
6803
|
keyStorageType
|
|
6763
6804
|
},
|
|
6764
6805
|
children: /* @__PURE__ */ jsxs(VolrModalProvider, { children: [
|
|
6806
|
+
/* @__PURE__ */ jsx(
|
|
6807
|
+
MigrationCoordinator,
|
|
6808
|
+
{
|
|
6809
|
+
onShowOnboarding: () => setShowOnboarding(true),
|
|
6810
|
+
onHideOnboarding: () => setShowOnboarding(false)
|
|
6811
|
+
}
|
|
6812
|
+
),
|
|
6765
6813
|
/* @__PURE__ */ jsx(
|
|
6766
6814
|
OAuthCallbackHandler,
|
|
6767
6815
|
{
|
|
@@ -6804,6 +6852,130 @@ function VolrUIProviderInner({
|
|
|
6804
6852
|
}
|
|
6805
6853
|
) }) });
|
|
6806
6854
|
}
|
|
6855
|
+
function normalizeOrigin(input) {
|
|
6856
|
+
try {
|
|
6857
|
+
const u = new URL(input);
|
|
6858
|
+
return `${u.protocol}//${u.host}`;
|
|
6859
|
+
} catch {
|
|
6860
|
+
return input;
|
|
6861
|
+
}
|
|
6862
|
+
}
|
|
6863
|
+
function MigrationCoordinator({
|
|
6864
|
+
onShowOnboarding,
|
|
6865
|
+
onHideOnboarding
|
|
6866
|
+
}) {
|
|
6867
|
+
const { user, setUser } = useVolrContext();
|
|
6868
|
+
const { client } = useInternalAuth();
|
|
6869
|
+
const [running, setRunning] = useState(false);
|
|
6870
|
+
useEffect(() => {
|
|
6871
|
+
if (typeof window === "undefined") return;
|
|
6872
|
+
const handler = (event) => {
|
|
6873
|
+
const data = event.data;
|
|
6874
|
+
if (data?.type === "VOLR_MIGRATION_DONE") {
|
|
6875
|
+
client.refreshSession().then((u) => u && setUser(u)).catch(() => void 0);
|
|
6876
|
+
onHideOnboarding();
|
|
6877
|
+
}
|
|
6878
|
+
};
|
|
6879
|
+
window.addEventListener("message", handler);
|
|
6880
|
+
return () => window.removeEventListener("message", handler);
|
|
6881
|
+
}, [client, setUser, onHideOnboarding]);
|
|
6882
|
+
useEffect(() => {
|
|
6883
|
+
if (typeof window === "undefined") return;
|
|
6884
|
+
if (running) return;
|
|
6885
|
+
const params = new URLSearchParams(window.location.search);
|
|
6886
|
+
const migrationToken = params.get("migration_token");
|
|
6887
|
+
const sourceOriginParam = params.get("source_origin");
|
|
6888
|
+
const isTargetPopup = Boolean(migrationToken && sourceOriginParam);
|
|
6889
|
+
const migrateTo = params.get("volr_migrate_to");
|
|
6890
|
+
const isSourceFlow = Boolean(migrateTo);
|
|
6891
|
+
if (!isTargetPopup && !isSourceFlow) {
|
|
6892
|
+
return;
|
|
6893
|
+
}
|
|
6894
|
+
const run = async () => {
|
|
6895
|
+
setRunning(true);
|
|
6896
|
+
try {
|
|
6897
|
+
if (isTargetPopup) {
|
|
6898
|
+
const sourceOrigin2 = normalizeOrigin(sourceOriginParam);
|
|
6899
|
+
const token2 = migrationToken;
|
|
6900
|
+
const refreshedUser2 = await client.refreshSession();
|
|
6901
|
+
const effectiveUser2 = refreshedUser2 ?? user;
|
|
6902
|
+
if (refreshedUser2) setUser(refreshedUser2);
|
|
6903
|
+
if (!effectiveUser2?.id || !effectiveUser2?.projectId) {
|
|
6904
|
+
throw new Error(
|
|
6905
|
+
"Migration requires an active session on the target site. Please log in first."
|
|
6906
|
+
);
|
|
6907
|
+
}
|
|
6908
|
+
const { requestSeedFromOpener } = await import('@volr/react');
|
|
6909
|
+
const seed = await requestSeedFromOpener(sourceOrigin2, token2);
|
|
6910
|
+
await completeMigration({
|
|
6911
|
+
client,
|
|
6912
|
+
userId: seed.userId,
|
|
6913
|
+
projectId: seed.projectId,
|
|
6914
|
+
migrationToken: token2,
|
|
6915
|
+
masterSeed: seed.masterSeed,
|
|
6916
|
+
rpName: effectiveUser2.projectName ?? "Volr",
|
|
6917
|
+
userEmail: effectiveUser2.email ?? null
|
|
6918
|
+
});
|
|
6919
|
+
try {
|
|
6920
|
+
window.opener?.postMessage({ type: "VOLR_MIGRATION_DONE" }, "*");
|
|
6921
|
+
} catch {
|
|
6922
|
+
}
|
|
6923
|
+
window.close();
|
|
6924
|
+
return;
|
|
6925
|
+
}
|
|
6926
|
+
const targetOrigin = normalizeOrigin(migrateTo);
|
|
6927
|
+
const sourceOrigin = window.location.origin;
|
|
6928
|
+
const refreshedUser = await client.refreshSession();
|
|
6929
|
+
const effectiveUser = refreshedUser ?? user;
|
|
6930
|
+
if (refreshedUser) setUser(refreshedUser);
|
|
6931
|
+
if (!effectiveUser?.id || !effectiveUser?.projectId) {
|
|
6932
|
+
throw new Error(
|
|
6933
|
+
"Migration requires an active session on the source site. Please log in first."
|
|
6934
|
+
);
|
|
6935
|
+
}
|
|
6936
|
+
const currentRpId = getCurrentRpId();
|
|
6937
|
+
const sourcePasskey = effectiveUser.registeredPasskeys?.find((p) => p?.rpId === currentRpId) ?? null;
|
|
6938
|
+
if (!sourcePasskey?.credentialId || !sourcePasskey?.blobUrl || !sourcePasskey?.prfInput) {
|
|
6939
|
+
throw new Error(
|
|
6940
|
+
`No passkey registered for source rpId=${currentRpId}. Cannot migrate from this site.`
|
|
6941
|
+
);
|
|
6942
|
+
}
|
|
6943
|
+
const token = await requestMigration({ client, targetOrigin });
|
|
6944
|
+
const entropy = await decryptEntropyForMigration({
|
|
6945
|
+
client,
|
|
6946
|
+
userId: effectiveUser.id,
|
|
6947
|
+
blobUrl: sourcePasskey.blobUrl,
|
|
6948
|
+
prfInput: sourcePasskey.prfInput,
|
|
6949
|
+
credentialId: sourcePasskey.credentialId,
|
|
6950
|
+
rpName: effectiveUser.projectName ?? "Volr"
|
|
6951
|
+
});
|
|
6952
|
+
const cleanup = listenForSeedRequests(
|
|
6953
|
+
[targetOrigin],
|
|
6954
|
+
async () => entropy,
|
|
6955
|
+
() => ({ userId: effectiveUser.id, projectId: effectiveUser.projectId })
|
|
6956
|
+
);
|
|
6957
|
+
const url = new URL(targetOrigin);
|
|
6958
|
+
url.searchParams.set("migration_token", token.migrationToken);
|
|
6959
|
+
url.searchParams.set("source_origin", sourceOrigin);
|
|
6960
|
+
window.open(
|
|
6961
|
+
url.toString(),
|
|
6962
|
+
"volr_migration",
|
|
6963
|
+
"width=500,height=650,left=100,top=100,popup=1"
|
|
6964
|
+
);
|
|
6965
|
+
onShowOnboarding();
|
|
6966
|
+
setTimeout(() => cleanup(), 2 * 60 * 1e3);
|
|
6967
|
+
return;
|
|
6968
|
+
} finally {
|
|
6969
|
+
setRunning(false);
|
|
6970
|
+
}
|
|
6971
|
+
};
|
|
6972
|
+
run().catch((e) => {
|
|
6973
|
+
console.error("[MigrationCoordinator] failed:", e);
|
|
6974
|
+
setRunning(false);
|
|
6975
|
+
});
|
|
6976
|
+
}, [client, user, setUser, running, onShowOnboarding, onHideOnboarding]);
|
|
6977
|
+
return null;
|
|
6978
|
+
}
|
|
6807
6979
|
function AccountModalPortal() {
|
|
6808
6980
|
const { isOpen, mode, close } = useVolrModal();
|
|
6809
6981
|
const [portalRoot, setPortalRoot] = useState(null);
|
|
@@ -7033,6 +7205,7 @@ function OnboardingChecker({
|
|
|
7033
7205
|
const { user, provider, isLoading } = useVolrContext();
|
|
7034
7206
|
const { isOpen: isModalOpen } = useVolrModal();
|
|
7035
7207
|
const modalWasOpened = React13.useRef(false);
|
|
7208
|
+
const pendingMismatchOnboarding = React13.useRef(false);
|
|
7036
7209
|
useEffect(() => {
|
|
7037
7210
|
if (isModalOpen) {
|
|
7038
7211
|
modalWasOpened.current = true;
|
|
@@ -7042,15 +7215,21 @@ function OnboardingChecker({
|
|
|
7042
7215
|
if (isLoading) {
|
|
7043
7216
|
return;
|
|
7044
7217
|
}
|
|
7218
|
+
const passkeyDomainMismatch = isPasskeyDomainMismatch(user);
|
|
7045
7219
|
if (isModalOpen) {
|
|
7220
|
+
if (passkeyDomainMismatch) {
|
|
7221
|
+
pendingMismatchOnboarding.current = true;
|
|
7222
|
+
}
|
|
7046
7223
|
onHideOnboarding();
|
|
7047
7224
|
return;
|
|
7048
7225
|
}
|
|
7049
7226
|
if (modalWasOpened.current) {
|
|
7050
|
-
|
|
7051
|
-
|
|
7227
|
+
if (!passkeyDomainMismatch && !pendingMismatchOnboarding.current) {
|
|
7228
|
+
onHideOnboarding();
|
|
7229
|
+
return;
|
|
7230
|
+
}
|
|
7052
7231
|
}
|
|
7053
|
-
if (user?.keyStorageType) {
|
|
7232
|
+
if (user?.keyStorageType && !passkeyDomainMismatch && !pendingMismatchOnboarding.current) {
|
|
7054
7233
|
onHideOnboarding();
|
|
7055
7234
|
return;
|
|
7056
7235
|
}
|
|
@@ -7058,6 +7237,15 @@ function OnboardingChecker({
|
|
|
7058
7237
|
onHideOnboarding();
|
|
7059
7238
|
return;
|
|
7060
7239
|
}
|
|
7240
|
+
if (pendingMismatchOnboarding.current) {
|
|
7241
|
+
pendingMismatchOnboarding.current = false;
|
|
7242
|
+
onShowOnboarding();
|
|
7243
|
+
return;
|
|
7244
|
+
}
|
|
7245
|
+
if (passkeyDomainMismatch) {
|
|
7246
|
+
onShowOnboarding();
|
|
7247
|
+
return;
|
|
7248
|
+
}
|
|
7061
7249
|
if (user && enforceSelection) {
|
|
7062
7250
|
if (!keyStorageType) {
|
|
7063
7251
|
console.error(
|