@volr/react 0.1.69 → 0.1.71
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 +70 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +70 -71
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -526,15 +526,52 @@ interface UseVolrLoginReturn {
|
|
|
526
526
|
declare function useVolrLogin(): UseVolrLoginReturn;
|
|
527
527
|
|
|
528
528
|
interface UseVolrAuthCallbackOptions {
|
|
529
|
+
/**
|
|
530
|
+
* Called when OAuth authentication is successful
|
|
531
|
+
*/
|
|
529
532
|
onSuccess?: (user: VolrUser) => void;
|
|
533
|
+
/**
|
|
534
|
+
* Called when OAuth authentication fails
|
|
535
|
+
*/
|
|
530
536
|
onError?: (error: string) => void;
|
|
537
|
+
/**
|
|
538
|
+
* If true, automatically clears the URL query params after processing
|
|
539
|
+
* @default true
|
|
540
|
+
*/
|
|
541
|
+
clearUrlParams?: boolean;
|
|
531
542
|
}
|
|
532
543
|
interface UseVolrAuthCallbackReturn {
|
|
544
|
+
/** Whether the callback is being processed */
|
|
533
545
|
isLoading: boolean;
|
|
546
|
+
/** Error message if authentication failed */
|
|
534
547
|
error: string | null;
|
|
548
|
+
/** Whether this is a new user (first time sign in) */
|
|
535
549
|
isNewUser: boolean;
|
|
550
|
+
/** The authenticated user object */
|
|
536
551
|
user: VolrUser | null;
|
|
537
552
|
}
|
|
553
|
+
/**
|
|
554
|
+
* Hook to handle OAuth callback after social login redirect.
|
|
555
|
+
*
|
|
556
|
+
* Usage:
|
|
557
|
+
* ```tsx
|
|
558
|
+
* // In your /auth/callback page
|
|
559
|
+
* function AuthCallbackPage() {
|
|
560
|
+
* const { isLoading, error, user, isNewUser } = useVolrAuthCallback({
|
|
561
|
+
* onSuccess: (user) => {
|
|
562
|
+
* navigate('/dashboard');
|
|
563
|
+
* },
|
|
564
|
+
* onError: (error) => {
|
|
565
|
+
* navigate('/login?error=' + encodeURIComponent(error));
|
|
566
|
+
* },
|
|
567
|
+
* });
|
|
568
|
+
*
|
|
569
|
+
* if (isLoading) return <LoadingSpinner />;
|
|
570
|
+
* if (error) return <ErrorMessage message={error} />;
|
|
571
|
+
* return null;
|
|
572
|
+
* }
|
|
573
|
+
* ```
|
|
574
|
+
*/
|
|
538
575
|
declare function useVolrAuthCallback(options?: UseVolrAuthCallbackOptions): UseVolrAuthCallbackReturn;
|
|
539
576
|
|
|
540
577
|
type Erc20Token = {
|
package/dist/index.d.ts
CHANGED
|
@@ -526,15 +526,52 @@ interface UseVolrLoginReturn {
|
|
|
526
526
|
declare function useVolrLogin(): UseVolrLoginReturn;
|
|
527
527
|
|
|
528
528
|
interface UseVolrAuthCallbackOptions {
|
|
529
|
+
/**
|
|
530
|
+
* Called when OAuth authentication is successful
|
|
531
|
+
*/
|
|
529
532
|
onSuccess?: (user: VolrUser) => void;
|
|
533
|
+
/**
|
|
534
|
+
* Called when OAuth authentication fails
|
|
535
|
+
*/
|
|
530
536
|
onError?: (error: string) => void;
|
|
537
|
+
/**
|
|
538
|
+
* If true, automatically clears the URL query params after processing
|
|
539
|
+
* @default true
|
|
540
|
+
*/
|
|
541
|
+
clearUrlParams?: boolean;
|
|
531
542
|
}
|
|
532
543
|
interface UseVolrAuthCallbackReturn {
|
|
544
|
+
/** Whether the callback is being processed */
|
|
533
545
|
isLoading: boolean;
|
|
546
|
+
/** Error message if authentication failed */
|
|
534
547
|
error: string | null;
|
|
548
|
+
/** Whether this is a new user (first time sign in) */
|
|
535
549
|
isNewUser: boolean;
|
|
550
|
+
/** The authenticated user object */
|
|
536
551
|
user: VolrUser | null;
|
|
537
552
|
}
|
|
553
|
+
/**
|
|
554
|
+
* Hook to handle OAuth callback after social login redirect.
|
|
555
|
+
*
|
|
556
|
+
* Usage:
|
|
557
|
+
* ```tsx
|
|
558
|
+
* // In your /auth/callback page
|
|
559
|
+
* function AuthCallbackPage() {
|
|
560
|
+
* const { isLoading, error, user, isNewUser } = useVolrAuthCallback({
|
|
561
|
+
* onSuccess: (user) => {
|
|
562
|
+
* navigate('/dashboard');
|
|
563
|
+
* },
|
|
564
|
+
* onError: (error) => {
|
|
565
|
+
* navigate('/login?error=' + encodeURIComponent(error));
|
|
566
|
+
* },
|
|
567
|
+
* });
|
|
568
|
+
*
|
|
569
|
+
* if (isLoading) return <LoadingSpinner />;
|
|
570
|
+
* if (error) return <ErrorMessage message={error} />;
|
|
571
|
+
* return null;
|
|
572
|
+
* }
|
|
573
|
+
* ```
|
|
574
|
+
*/
|
|
538
575
|
declare function useVolrAuthCallback(options?: UseVolrAuthCallbackOptions): UseVolrAuthCallbackReturn;
|
|
539
576
|
|
|
540
577
|
type Erc20Token = {
|
package/dist/index.js
CHANGED
|
@@ -18667,45 +18667,15 @@ function useVolrLogin() {
|
|
|
18667
18667
|
handlePasskeyComplete
|
|
18668
18668
|
};
|
|
18669
18669
|
}
|
|
18670
|
-
function createAxiosInstance(baseUrl, apiKey) {
|
|
18671
|
-
const instance = axios.create({
|
|
18672
|
-
baseURL: baseUrl.replace(/\/+$/, ""),
|
|
18673
|
-
// Remove trailing slashes
|
|
18674
|
-
withCredentials: true,
|
|
18675
|
-
// Include cookies
|
|
18676
|
-
headers: {
|
|
18677
|
-
"Content-Type": "application/json"
|
|
18678
|
-
}
|
|
18679
|
-
});
|
|
18680
|
-
instance.interceptors.request.use((config) => {
|
|
18681
|
-
if (apiKey) {
|
|
18682
|
-
config.headers["X-API-Key"] = apiKey;
|
|
18683
|
-
}
|
|
18684
|
-
return config;
|
|
18685
|
-
});
|
|
18686
|
-
instance.interceptors.response.use(
|
|
18687
|
-
(response) => response,
|
|
18688
|
-
(error) => {
|
|
18689
|
-
if (error.response?.data) {
|
|
18690
|
-
const errorData = error.response.data;
|
|
18691
|
-
if (errorData.error?.message) {
|
|
18692
|
-
error.message = errorData.error.message;
|
|
18693
|
-
}
|
|
18694
|
-
}
|
|
18695
|
-
return Promise.reject(error);
|
|
18696
|
-
}
|
|
18697
|
-
);
|
|
18698
|
-
return instance;
|
|
18699
|
-
}
|
|
18700
|
-
|
|
18701
|
-
// src/hooks/useVolrAuthCallback.ts
|
|
18702
18670
|
function useVolrAuthCallback(options = {}) {
|
|
18703
|
-
const {
|
|
18704
|
-
const {
|
|
18671
|
+
const { clearUrlParams = true } = options;
|
|
18672
|
+
const { setUser } = useVolrContext();
|
|
18673
|
+
const { setAccessToken, setRefreshToken, client } = useInternalAuth();
|
|
18705
18674
|
const [isLoading, setIsLoading] = useState(true);
|
|
18706
18675
|
const [error, setError] = useState(null);
|
|
18707
18676
|
const [isNewUser, setIsNewUser] = useState(false);
|
|
18708
18677
|
const [user, setLocalUser] = useState(null);
|
|
18678
|
+
const hasProcessed = useRef(false);
|
|
18709
18679
|
const toVolrUser = useCallback((u) => {
|
|
18710
18680
|
return {
|
|
18711
18681
|
id: u.id,
|
|
@@ -18721,24 +18691,31 @@ function useVolrAuthCallback(options = {}) {
|
|
|
18721
18691
|
credentialId: u.credentialId ?? void 0
|
|
18722
18692
|
};
|
|
18723
18693
|
}, []);
|
|
18724
|
-
const apiBaseUrl = resolveApiBaseUrl(config);
|
|
18725
18694
|
useEffect(() => {
|
|
18726
18695
|
const handleCallback = async () => {
|
|
18727
18696
|
if (typeof window === "undefined") return;
|
|
18697
|
+
if (hasProcessed.current) return;
|
|
18698
|
+
hasProcessed.current = true;
|
|
18728
18699
|
const searchParams = new URLSearchParams(window.location.search);
|
|
18729
|
-
const
|
|
18700
|
+
const authCode = searchParams.get("code");
|
|
18730
18701
|
const errorParam = searchParams.get("error");
|
|
18731
|
-
const userId = searchParams.get("userId");
|
|
18732
18702
|
const isNew = searchParams.get("isNewUser") === "true";
|
|
18733
18703
|
if (errorParam) {
|
|
18734
|
-
const errorMsg = `Authentication failed: ${errorParam}`;
|
|
18704
|
+
const errorMsg = `Authentication failed: ${errorParam.replace(/_/g, " ")}`;
|
|
18705
|
+
setError(errorMsg);
|
|
18706
|
+
setIsLoading(false);
|
|
18707
|
+
options.onError?.(errorMsg);
|
|
18708
|
+
return;
|
|
18709
|
+
}
|
|
18710
|
+
if (!authCode) {
|
|
18711
|
+
const errorMsg = "No authorization code found. Please try logging in again.";
|
|
18735
18712
|
setError(errorMsg);
|
|
18736
18713
|
setIsLoading(false);
|
|
18737
18714
|
options.onError?.(errorMsg);
|
|
18738
18715
|
return;
|
|
18739
18716
|
}
|
|
18740
|
-
if (
|
|
18741
|
-
const errorMsg = "Invalid
|
|
18717
|
+
if (!authCode.startsWith("volr_auth_")) {
|
|
18718
|
+
const errorMsg = "Invalid authorization code format";
|
|
18742
18719
|
setError(errorMsg);
|
|
18743
18720
|
setIsLoading(false);
|
|
18744
18721
|
options.onError?.(errorMsg);
|
|
@@ -18746,45 +18723,44 @@ function useVolrAuthCallback(options = {}) {
|
|
|
18746
18723
|
}
|
|
18747
18724
|
try {
|
|
18748
18725
|
setIsNewUser(isNew);
|
|
18749
|
-
await
|
|
18750
|
-
const
|
|
18751
|
-
|
|
18752
|
-
|
|
18753
|
-
);
|
|
18754
|
-
const userRes = await api.get(`/auth/onboarding/${userId}`);
|
|
18755
|
-
if (!userRes.data?.ok) {
|
|
18756
|
-
throw new Error("Failed to fetch user details");
|
|
18757
|
-
}
|
|
18758
|
-
const currentRefreshToken = client.getRefreshToken();
|
|
18759
|
-
if (!currentRefreshToken) {
|
|
18760
|
-
throw new Error("No refresh token available. Please log in again.");
|
|
18761
|
-
}
|
|
18762
|
-
const refreshRes = await api.post("/auth/refresh", { refreshToken: currentRefreshToken });
|
|
18763
|
-
if (!refreshRes.data?.ok) {
|
|
18764
|
-
throw new Error("Failed to refresh session");
|
|
18726
|
+
const response = await client.post("/auth/token/exchange", { code: authCode });
|
|
18727
|
+
const { user: userData, accessToken, refreshToken } = response;
|
|
18728
|
+
if (!accessToken) {
|
|
18729
|
+
throw new Error("No access token received from server");
|
|
18765
18730
|
}
|
|
18766
|
-
const userData = refreshRes.data.data.user;
|
|
18767
|
-
const accessToken = refreshRes.data.data.accessToken;
|
|
18768
|
-
const newRefreshToken = refreshRes.data.data.refreshToken;
|
|
18769
18731
|
setAccessToken(accessToken);
|
|
18770
|
-
if (
|
|
18771
|
-
setRefreshToken(
|
|
18732
|
+
if (refreshToken) {
|
|
18733
|
+
setRefreshToken(refreshToken);
|
|
18772
18734
|
}
|
|
18773
18735
|
const volrUser = toVolrUser(userData);
|
|
18774
18736
|
setUser(volrUser);
|
|
18775
18737
|
setLocalUser(volrUser);
|
|
18738
|
+
if (clearUrlParams && typeof window !== "undefined") {
|
|
18739
|
+
const url = new URL(window.location.href);
|
|
18740
|
+
url.search = "";
|
|
18741
|
+
window.history.replaceState({}, "", url.toString());
|
|
18742
|
+
}
|
|
18776
18743
|
setIsLoading(false);
|
|
18777
18744
|
options.onSuccess?.(volrUser);
|
|
18778
18745
|
} catch (err) {
|
|
18779
|
-
console.error("
|
|
18780
|
-
|
|
18746
|
+
console.error("[useVolrAuthCallback] Token exchange error:", err);
|
|
18747
|
+
let errorMsg = "Failed to complete authentication";
|
|
18748
|
+
if (err instanceof Error) {
|
|
18749
|
+
if (err.message.includes("AUTH_CODE_EXPIRED")) {
|
|
18750
|
+
errorMsg = "Login link has expired. Please try again.";
|
|
18751
|
+
} else if (err.message.includes("AUTH_INVALID_CODE")) {
|
|
18752
|
+
errorMsg = "Invalid login link. Please try again.";
|
|
18753
|
+
} else {
|
|
18754
|
+
errorMsg = err.message;
|
|
18755
|
+
}
|
|
18756
|
+
}
|
|
18781
18757
|
setError(errorMsg);
|
|
18782
18758
|
setIsLoading(false);
|
|
18783
18759
|
options.onError?.(errorMsg);
|
|
18784
18760
|
}
|
|
18785
18761
|
};
|
|
18786
18762
|
handleCallback();
|
|
18787
|
-
}, [
|
|
18763
|
+
}, []);
|
|
18788
18764
|
return {
|
|
18789
18765
|
isLoading,
|
|
18790
18766
|
error,
|
|
@@ -18866,10 +18842,8 @@ function useDepositListener(input) {
|
|
|
18866
18842
|
try {
|
|
18867
18843
|
if (!rpcUrlRef.current) {
|
|
18868
18844
|
rpcUrlRef.current = await getRpcUrl(input.chainId);
|
|
18869
|
-
console.log("[DepositListener] RPC URL:", rpcUrlRef.current);
|
|
18870
18845
|
}
|
|
18871
18846
|
const initial = await fetchBalance();
|
|
18872
|
-
console.log("[DepositListener] Initial balance:", initial.toString());
|
|
18873
18847
|
if (cancelled) return;
|
|
18874
18848
|
setStatus({ state: "listening", balance: initial });
|
|
18875
18849
|
} catch (e) {
|
|
@@ -18879,16 +18853,13 @@ function useDepositListener(input) {
|
|
|
18879
18853
|
return;
|
|
18880
18854
|
}
|
|
18881
18855
|
const intervalMs = input.pollIntervalMs ?? config.deposit?.pollIntervalMs ?? 6e3;
|
|
18882
|
-
console.log("[DepositListener] Polling interval:", intervalMs, "ms");
|
|
18883
18856
|
intervalRef.current = window.setInterval(async () => {
|
|
18884
18857
|
try {
|
|
18885
18858
|
const current = await fetchBalance();
|
|
18886
|
-
console.log("[DepositListener] Current balance:", current.toString());
|
|
18887
18859
|
if (cancelled) return;
|
|
18888
18860
|
setStatus((prev) => {
|
|
18889
18861
|
if (prev.state === "listening") {
|
|
18890
18862
|
if (current > prev.balance) {
|
|
18891
|
-
console.log("[DepositListener] \u2705 DEPOSIT DETECTED! Previous:", prev.balance.toString(), "New:", current.toString());
|
|
18892
18863
|
return {
|
|
18893
18864
|
state: "detected",
|
|
18894
18865
|
previousBalance: prev.balance,
|
|
@@ -18897,7 +18868,6 @@ function useDepositListener(input) {
|
|
|
18897
18868
|
};
|
|
18898
18869
|
}
|
|
18899
18870
|
if (current !== prev.balance) {
|
|
18900
|
-
console.log("[DepositListener] \u26A0\uFE0F Balance changed (decreased or other). Previous:", prev.balance.toString(), "New:", current.toString());
|
|
18901
18871
|
return {
|
|
18902
18872
|
state: "detected",
|
|
18903
18873
|
previousBalance: prev.balance,
|
|
@@ -18908,7 +18878,6 @@ function useDepositListener(input) {
|
|
|
18908
18878
|
return prev;
|
|
18909
18879
|
}
|
|
18910
18880
|
if (prev.state === "detected") {
|
|
18911
|
-
console.log("[DepositListener] Resuming listening from new balance:", current.toString());
|
|
18912
18881
|
return { state: "listening", balance: current };
|
|
18913
18882
|
}
|
|
18914
18883
|
return prev;
|
|
@@ -19341,6 +19310,36 @@ function useMpcConnection() {
|
|
|
19341
19310
|
error
|
|
19342
19311
|
};
|
|
19343
19312
|
}
|
|
19313
|
+
function createAxiosInstance(baseUrl, apiKey) {
|
|
19314
|
+
const instance = axios.create({
|
|
19315
|
+
baseURL: baseUrl.replace(/\/+$/, ""),
|
|
19316
|
+
// Remove trailing slashes
|
|
19317
|
+
withCredentials: true,
|
|
19318
|
+
// Include cookies
|
|
19319
|
+
headers: {
|
|
19320
|
+
"Content-Type": "application/json"
|
|
19321
|
+
}
|
|
19322
|
+
});
|
|
19323
|
+
instance.interceptors.request.use((config) => {
|
|
19324
|
+
if (apiKey) {
|
|
19325
|
+
config.headers["X-API-Key"] = apiKey;
|
|
19326
|
+
}
|
|
19327
|
+
return config;
|
|
19328
|
+
});
|
|
19329
|
+
instance.interceptors.response.use(
|
|
19330
|
+
(response) => response,
|
|
19331
|
+
(error) => {
|
|
19332
|
+
if (error.response?.data) {
|
|
19333
|
+
const errorData = error.response.data;
|
|
19334
|
+
if (errorData.error?.message) {
|
|
19335
|
+
error.message = errorData.error.message;
|
|
19336
|
+
}
|
|
19337
|
+
}
|
|
19338
|
+
return Promise.reject(error);
|
|
19339
|
+
}
|
|
19340
|
+
);
|
|
19341
|
+
return instance;
|
|
19342
|
+
}
|
|
19344
19343
|
|
|
19345
19344
|
// src/headless/blobs.ts
|
|
19346
19345
|
async function uploadBlobViaPresign(params) {
|