auth flow fix, validation for auth in steps /uploadContnt
This commit is contained in:
parent
7705908484
commit
3e9564d7b9
|
|
@ -18,15 +18,20 @@ export const WelcomeStep = ({ nextStep }: WelcomeStepProps) => {
|
|||
|
||||
console.log("💩💩💩 after useAuth");
|
||||
|
||||
const handleNextClick = async () => {
|
||||
const handleNextClick = async () => {
|
||||
if (tonConnectUI.connected) {
|
||||
await auth.mutateAsync();
|
||||
nextStep();
|
||||
} else {
|
||||
try {
|
||||
await tonConnectUI.openModal();
|
||||
await auth.mutateAsync();
|
||||
nextStep();
|
||||
} catch (error) {
|
||||
console.error('Failed to connect or authenticate:', error);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// const first = setTimeout(async () => {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import ReactPlayer from "react-player/lazy";
|
|||
import { useTonConnectUI } from "@tonconnect/ui-react";
|
||||
import { useWebApp } from "@vkruglikov/react-telegram-web-app";
|
||||
|
||||
import { Button } from "~/shared/ui/button";
|
||||
import { usePurchaseContent, useViewContent } from "~/shared/services/content";
|
||||
import { fromNanoTON } from "~/shared/utils";
|
||||
import {useCallback, useEffect, useMemo} from "react";
|
||||
|
|
@ -71,45 +72,9 @@ export const ViewContentPage = () => {
|
|||
}, []);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const mainButton = WebApp.MainButton;
|
||||
const secondaryButton = WebApp.SecondaryButton;
|
||||
|
||||
try {
|
||||
// Set main button color
|
||||
mainButton.color = '#e40615';
|
||||
mainButton.textColor = '#FFFFFF';
|
||||
|
||||
// Set secondary button color
|
||||
secondaryButton.color = '#363636';
|
||||
secondaryButton.textColor = '#FFFFFF';
|
||||
if (!haveLicense) {
|
||||
mainButton.text = `Купить за ${fromNanoTON(content?.data?.encrypted?.license?.resale?.price)} ТОН`;
|
||||
mainButton.show();
|
||||
mainButton.onClick(handleBuyContent);
|
||||
} else {
|
||||
mainButton.hide();
|
||||
}
|
||||
|
||||
secondaryButton.text = 'Загрузить свой контент';
|
||||
secondaryButton.show();
|
||||
secondaryButton.onClick(() => {
|
||||
WebApp.openTelegramLink('https://t.me/MY_UploaderRobot');
|
||||
});
|
||||
|
||||
return () => {
|
||||
mainButton.hide();
|
||||
mainButton.offClick(handleBuyContent);
|
||||
secondaryButton.hide();
|
||||
secondaryButton.offClick();
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error setting up Telegram WebApp buttons:', error);
|
||||
}
|
||||
}, [content, haveLicense, WebApp, handleBuyContent]);
|
||||
|
||||
return (
|
||||
<main className={"flex w-full flex-col gap-[50px] px-4"}>
|
||||
<main className={"min-h-screen flex w-full flex-col gap-[50px] px-4 "}>
|
||||
{content?.data?.content_type.startsWith("audio") && content?.data?.display_options?.metadata?.image && (
|
||||
<div className={"mt-[30px] h-[314px] w-full"}>
|
||||
<img
|
||||
|
|
@ -146,9 +111,10 @@ export const ViewContentPage = () => {
|
|||
</p>
|
||||
</section>
|
||||
|
||||
{/* {!haveLicense && <Button
|
||||
<div className="mt-auto pb-2">
|
||||
{!haveLicense && <Button
|
||||
onClick={handleBuyContent}
|
||||
className={"mb-4 mt-[30px] h-[48px]"}
|
||||
className={"mb-4 h-[48px]"}
|
||||
label={`Купить за ${fromNanoTON(content?.data?.encrypted?.license?.resale?.price)} ТОН`}
|
||||
includeArrows={true}
|
||||
/>
|
||||
|
|
@ -158,9 +124,10 @@ export const ViewContentPage = () => {
|
|||
onClick={() => {
|
||||
WebApp.openTelegramLink(`https://t.me/MY_UploaderRobot`);
|
||||
}}
|
||||
className={"mb-4 mt-[-20px] h-[48px] bg-darkred"}
|
||||
className={"h-[48px] bg-darkred"}
|
||||
label={`Загрузить свой контент`}
|
||||
/> */}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
import { ReactNode, useMemo, useState } from "react";
|
||||
import { useTonConnectUI } from "@tonconnect/ui-react";
|
||||
import { ReactNode, useEffect, useMemo, useState } from "react";
|
||||
|
||||
const CHECK_INTERVAL = 20000;
|
||||
|
||||
|
||||
export const useSteps = (
|
||||
sections: ({
|
||||
|
|
@ -9,15 +13,24 @@ export const useSteps = (
|
|||
prevStep(): void;
|
||||
}) => ReactNode[],
|
||||
) => {
|
||||
|
||||
const [tonConnectUI] = useTonConnectUI();
|
||||
|
||||
const [step, setStep] = useState(0);
|
||||
|
||||
const nextStep = () => {
|
||||
return setStep((s) => s + 1);
|
||||
};
|
||||
// If connection is lost, reset the step
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
if (!tonConnectUI.connected && step !== 0) {
|
||||
setStep(0);
|
||||
}
|
||||
}, CHECK_INTERVAL);
|
||||
|
||||
const prevStep = () => {
|
||||
return setStep((s) => s - 1);
|
||||
};
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const nextStep = () => setStep((s) => s + 1);
|
||||
const prevStep = () => setStep((s) => s - 1);
|
||||
|
||||
const ActiveSection = useMemo(() => {
|
||||
return sections({ nextStep, prevStep })[step];
|
||||
|
|
|
|||
|
|
@ -13,80 +13,103 @@ export const useAuth = () => {
|
|||
const [tonConnectUI] = useTonConnectUI();
|
||||
const interval = useRef<ReturnType<typeof setInterval> | undefined>();
|
||||
|
||||
return useMutation(["auth"], async () => {
|
||||
clearInterval(interval.current);
|
||||
|
||||
if (!wallet) {
|
||||
localStorage.removeItem(sessionStorageKey);
|
||||
|
||||
const refreshPayload = async () => {
|
||||
tonConnectUI.setConnectRequestParameters({ state: "loading" });
|
||||
|
||||
const value = await request
|
||||
.post<{
|
||||
auth_v1_token: string;
|
||||
}>("/auth.twa", {
|
||||
twa_data: WebApp.initData,
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error("Error in authentication request: ", error);
|
||||
throw new Error("Failed to authenticate.");
|
||||
});
|
||||
if (!value) {
|
||||
tonConnectUI.setConnectRequestParameters(null);
|
||||
} else {
|
||||
tonConnectUI.setConnectRequestParameters({
|
||||
state: "ready",
|
||||
value: {
|
||||
tonProof: value?.data?.auth_v1_token,
|
||||
},
|
||||
});
|
||||
const waitForWalletProof = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => reject(new Error("Timeout waiting for proof")), 30000);
|
||||
const checkProof = setInterval(() => {
|
||||
const currentWallet = tonConnectUI.wallet;
|
||||
if (
|
||||
currentWallet?.connectItems?.tonProof &&
|
||||
!("error" in currentWallet.connectItems.tonProof)
|
||||
) {
|
||||
clearInterval(checkProof);
|
||||
clearTimeout(timeout);
|
||||
resolve(currentWallet.connectItems.tonProof.proof);
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
|
||||
void refreshPayload();
|
||||
setInterval(refreshPayload, payloadTTLMS);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
wallet.connectItems?.tonProof &&
|
||||
!("error" in wallet.connectItems.tonProof)
|
||||
) {
|
||||
const tonProof = wallet.connectItems.tonProof.proof;
|
||||
|
||||
console.log("DEBUG TON-PROOF", tonProof);
|
||||
|
||||
request
|
||||
.post<{
|
||||
const makeAuthRequest = async (params: {
|
||||
twa_data: string;
|
||||
ton_proof?: {
|
||||
account: any;
|
||||
ton_proof: any;
|
||||
};
|
||||
}) => {
|
||||
const res = await request.post<{
|
||||
connected_wallet: null | {
|
||||
version: string;
|
||||
address: string;
|
||||
ton_balance: string;
|
||||
};
|
||||
auth_v1_token: string;
|
||||
}>("/auth.twa", {
|
||||
}>("/auth.twa", params);
|
||||
|
||||
if (res?.data?.auth_v1_token) {
|
||||
localStorage.setItem(sessionStorageKey, res.data.auth_v1_token);
|
||||
} else {
|
||||
throw new Error("Failed to get auth token");
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
return useMutation(["auth"], async () => {
|
||||
clearInterval(interval.current);
|
||||
console.log("DEBUG: Starting auth flow");
|
||||
|
||||
// Case 1: Not connected - need to connect and get proof
|
||||
if (!tonConnectUI.connected) {
|
||||
console.log("DEBUG: No wallet connection, starting flow");
|
||||
localStorage.removeItem(sessionStorageKey);
|
||||
|
||||
const refreshPayload = async () => {
|
||||
tonConnectUI.setConnectRequestParameters({ state: "loading" });
|
||||
const value = await request.post<{ auth_v1_token: string }>("/auth.twa", {
|
||||
twa_data: WebApp.initData,
|
||||
});
|
||||
|
||||
if (value?.data?.auth_v1_token) {
|
||||
tonConnectUI.setConnectRequestParameters({
|
||||
state: "ready",
|
||||
value: { tonProof: value.data.auth_v1_token },
|
||||
});
|
||||
} else {
|
||||
tonConnectUI.setConnectRequestParameters(null);
|
||||
}
|
||||
};
|
||||
|
||||
await refreshPayload();
|
||||
interval.current = setInterval(refreshPayload, payloadTTLMS);
|
||||
|
||||
const tonProof = await waitForWalletProof();
|
||||
console.log("DEBUG: Got initial proof", tonProof);
|
||||
|
||||
return makeAuthRequest({
|
||||
twa_data: WebApp.initData,
|
||||
ton_proof: {
|
||||
account: tonConnectUI.wallet!.account,
|
||||
ton_proof: tonProof,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Case 2: Connected with proof - use it
|
||||
if (wallet?.connectItems?.tonProof && !("error" in wallet.connectItems.tonProof)) {
|
||||
console.log("DEBUG: Using existing proof");
|
||||
return makeAuthRequest({
|
||||
twa_data: WebApp.initData,
|
||||
ton_proof: {
|
||||
account: wallet.account,
|
||||
ton_proof: tonProof,
|
||||
ton_proof: wallet.connectItems.tonProof.proof,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
if (res?.data?.auth_v1_token) {
|
||||
localStorage.setItem(sessionStorageKey, res?.data?.auth_v1_token);
|
||||
} else {
|
||||
alert("Please try another wallet");
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error("Error in authentication request: ", error);
|
||||
throw new Error("Failed to authenticate.");
|
||||
});
|
||||
} else {
|
||||
void tonConnectUI.disconnect();
|
||||
localStorage.removeItem(sessionStorageKey)
|
||||
}
|
||||
|
||||
// Case 3: Connected without proof - already authenticated
|
||||
console.log("DEBUG: Connected without proof, proceeding without it");
|
||||
return makeAuthRequest({
|
||||
twa_data: WebApp.initData,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
@ -77,7 +77,7 @@ export const useRootStore = create<RootStore>((set) => ({
|
|||
authors: [],
|
||||
setAuthors: (authors) => set({ authors }),
|
||||
|
||||
royalty: [{ address: "", value: 100 }],
|
||||
royalty: [],
|
||||
setRoyalty: (royalty) => set({ royalty }),
|
||||
|
||||
price: 0.15,
|
||||
|
|
|
|||
Loading…
Reference in New Issue