diff --git a/apps/evm/.env.example b/apps/evm/.env.example
index 5b545ccb8..2558a46ef 100644
--- a/apps/evm/.env.example
+++ b/apps/evm/.env.example
@@ -33,3 +33,6 @@ SENTRY_AUTH_TOKEN=
# REDIS CACHE
KV_REST_API_URL="https://communal-hen-23354.upstash.io"
KV_REST_API_TOKEN=
+
+
+NEXT_PUBLIC_TURNSTILE_SITE_KEY=
\ No newline at end of file
diff --git a/apps/evm/package.json b/apps/evm/package.json
index 62473c0c5..fdc2a9e8e 100644
--- a/apps/evm/package.json
+++ b/apps/evm/package.json
@@ -28,6 +28,7 @@
"@gobob/utils": "workspace:^",
"@lingui/core": "catalog:",
"@lingui/react": "catalog:",
+ "@marsidev/react-turnstile": "^1.1.0",
"@next/third-parties": "catalog:",
"@react-aria/button": "catalog:",
"@react-aria/focus": "catalog:",
diff --git a/apps/evm/src/app/[lang]/nested-providers.tsx b/apps/evm/src/app/[lang]/nested-providers.tsx
index 4a241915b..747d14e05 100644
--- a/apps/evm/src/app/[lang]/nested-providers.tsx
+++ b/apps/evm/src/app/[lang]/nested-providers.tsx
@@ -10,7 +10,7 @@ import { useLocalStorage } from 'usehooks-ts';
import { isAddressEqual } from 'viem';
import { useAccount, useAccountEffect, useChainId, useConfig, useSwitchChain } from 'wagmi';
-import { Footer, Header, Layout, ReceiveModal } from '@/components';
+import { Footer, Header, Layout, ReceiveModal, TurnstileModal } from '@/components';
import { ConnectProvider } from '@/connect-ui';
import { isClient, L2_CHAIN, LocalStorageKey } from '@/constants';
import { useBalances, useGetUser, useLogout, useTokens } from '@/hooks';
@@ -148,6 +148,7 @@ export function NestedProviders({ children }: PropsWithChildren) {
{children}
+
diff --git a/apps/evm/src/app/[lang]/sign-up/SignUp.tsx b/apps/evm/src/app/[lang]/sign-up/SignUp.tsx
index 6b418ddc7..9adb1424a 100644
--- a/apps/evm/src/app/[lang]/sign-up/SignUp.tsx
+++ b/apps/evm/src/app/[lang]/sign-up/SignUp.tsx
@@ -5,6 +5,7 @@ import { Button, Divider, Flex, P, toast } from '@gobob/ui';
import { Trans, t } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { useMutation } from '@tanstack/react-query';
+import { useStore } from '@tanstack/react-store';
import { useParams, useRouter } from 'next/navigation';
import { FormEventHandler, Suspense, useEffect, useState } from 'react';
import { useAccount, useSwitchChain } from 'wagmi';
@@ -12,13 +13,14 @@ import { useAccount, useSwitchChain } from 'wagmi';
import { Auditors, HighlightText, ReferralInput } from './components';
import { StyledAuthCard, StyledH1 } from './SignUp.style';
+import { chakraPetch } from '@/app/fonts';
import { Geoblock, LoginSection, Main } from '@/components';
import { useConnectModal } from '@/connect-ui';
import { L1_CHAIN, L2_CHAIN, RoutesPath, isValidChain } from '@/constants';
import { useGetUser, useSignUp } from '@/hooks';
import { fusionKeys } from '@/lib/react-query';
+import { store } from '@/lib/store';
import { apiClient } from '@/utils';
-import { chakraPetch } from '@/app/fonts';
const SignUp = (): JSX.Element | null => {
const { address, chain } = useAccount();
@@ -30,9 +32,20 @@ const SignUp = (): JSX.Element | null => {
const params = useParams();
const { data: user } = useGetUser();
+ const { token: turnstileToken } = useStore(store, (state) => state.shared.turnstile);
+
const [referralCode, setReferralCode] = useState('');
- const { mutate: signUp, isPending: isLoadingSignUp } = useSignUp();
+ const { mutate: signUp, isPending: isLoadingSignUp } = useSignUp({
+ onSuccess: () =>
+ store.setState((s) => ({
+ ...s,
+ shared: {
+ ...s.shared,
+ turnstile: { isOpen: false }
+ }
+ }))
+ });
const {
mutateAsync: validateReferralCodeAsync,
@@ -74,7 +87,17 @@ const SignUp = (): JSX.Element | null => {
}
}
- return signUp({ address });
+ if (!turnstileToken) {
+ return store.setState((s) => ({
+ ...s,
+ shared: {
+ ...s.shared,
+ turnstile: { isOpen: true, onSuccess: (token) => signUp({ address, turnstileToken: token }) }
+ }
+ }));
+ }
+
+ return signUp({ address, turnstileToken });
}
});
}
@@ -83,7 +106,17 @@ const SignUp = (): JSX.Element | null => {
await switchChainAsync({ chainId: L1_CHAIN });
}
- return signUp({ address, referralCode });
+ if (!turnstileToken) {
+ return store.setState((s) => ({
+ ...s,
+ shared: {
+ ...s.shared,
+ turnstile: { isOpen: true, onSuccess: (token) => signUp({ address, turnstileToken: token }) }
+ }
+ }));
+ }
+
+ return signUp({ address, turnstileToken });
};
return (
diff --git a/apps/evm/src/components/SignUpButton/SignUpButton.tsx b/apps/evm/src/components/SignUpButton/SignUpButton.tsx
index c32c834b2..7a7e52714 100644
--- a/apps/evm/src/components/SignUpButton/SignUpButton.tsx
+++ b/apps/evm/src/components/SignUpButton/SignUpButton.tsx
@@ -3,10 +3,12 @@ import { Button, ButtonProps, toast } from '@gobob/ui';
import { Trans } from '@lingui/macro';
import { mergeProps } from '@react-aria/utils';
import { useAccount, useSwitchChain } from 'wagmi';
+import { useStore } from '@tanstack/react-store';
import { useConnectModal } from '@/connect-ui';
import { L2_CHAIN, isValidChain } from '@/constants';
import { useSignUp } from '@/hooks';
+import { store } from '@/lib/store';
type SignUpButtonProps = ButtonProps;
@@ -15,7 +17,18 @@ const SignUpButton = (props: SignUpButtonProps): JSX.Element => {
const { open } = useConnectModal();
const { address, chain } = useAccount();
- const { mutate: signUp, isPending: isSigningUp } = useSignUp();
+ const { token: turnstileToken } = useStore(store, (state) => state.shared.turnstile);
+
+ const { mutate: signUp, isPending: isSigningUp } = useSignUp({
+ onSuccess: () =>
+ store.setState((s) => ({
+ ...s,
+ shared: {
+ ...s.shared,
+ turnstile: { isOpen: false }
+ }
+ }))
+ });
const handlePress = async () => {
if (!address) {
@@ -30,7 +43,17 @@ const SignUpButton = (props: SignUpButtonProps): JSX.Element => {
}
}
- return signUp({ address });
+ if (!turnstileToken) {
+ return store.setState((s) => ({
+ ...s,
+ shared: {
+ ...s.shared,
+ turnstile: { isOpen: true, onSuccess: (token) => signUp({ address, turnstileToken: token }) }
+ }
+ }));
+ }
+
+ return signUp({ address, turnstileToken });
}
});
}
@@ -39,7 +62,17 @@ const SignUpButton = (props: SignUpButtonProps): JSX.Element => {
await switchChainAsync({ chainId: L2_CHAIN });
}
- return signUp({ address });
+ if (!turnstileToken) {
+ return store.setState((s) => ({
+ ...s,
+ shared: {
+ ...s.shared,
+ turnstile: { isOpen: true, onSuccess: (token) => signUp({ address, turnstileToken: token }) }
+ }
+ }));
+ }
+
+ return signUp({ address, turnstileToken });
};
return ;
diff --git a/apps/evm/src/components/TurnstileModal/TurnstileModal.tsx b/apps/evm/src/components/TurnstileModal/TurnstileModal.tsx
new file mode 100644
index 000000000..12bc35d5b
--- /dev/null
+++ b/apps/evm/src/components/TurnstileModal/TurnstileModal.tsx
@@ -0,0 +1,36 @@
+import { Modal, ModalBody, ModalHeader } from '@gobob/ui';
+import { useStore } from '@tanstack/react-store';
+import { Turnstile } from '@marsidev/react-turnstile';
+import { Trans } from '@lingui/macro';
+
+import { store } from '@/lib/store';
+
+const TurnstileModal = () => {
+ const { isOpen, onSuccess } = useStore(store, (state) => state.shared.turnstile);
+
+ const handleSuccess = (token: string) => {
+ onSuccess?.(token);
+
+ store.setState((s) => ({ ...s, shared: { ...s.shared, turnstile: { isOpen: false, token } } }));
+ };
+
+ return (
+ store.setState((s) => ({ ...s, shared: { ...s.shared, turnstile: { isOpen: false } } }))}
+ >
+
+ Verify you are human
+
+
+
+
+
+ );
+};
+
+export { TurnstileModal };
diff --git a/apps/evm/src/components/TurnstileModal/index.tsx b/apps/evm/src/components/TurnstileModal/index.tsx
new file mode 100644
index 000000000..86679b262
--- /dev/null
+++ b/apps/evm/src/components/TurnstileModal/index.tsx
@@ -0,0 +1 @@
+export { TurnstileModal } from './TurnstileModal';
diff --git a/apps/evm/src/components/index.ts b/apps/evm/src/components/index.ts
index 32ea246f7..f3eb3ac18 100644
--- a/apps/evm/src/components/index.ts
+++ b/apps/evm/src/components/index.ts
@@ -12,3 +12,4 @@ export * from './SignUpButton';
export * from './SpiceAmount';
export * from './Trapezoid';
export * from './WithdrawAlert';
+export * from './TurnstileModal';
diff --git a/apps/evm/src/hooks/tests/useSignUp.test.tsx b/apps/evm/src/hooks/tests/useSignUp.test.tsx
index dea5b66a6..b84f9c009 100644
--- a/apps/evm/src/hooks/tests/useSignUp.test.tsx
+++ b/apps/evm/src/hooks/tests/useSignUp.test.tsx
@@ -53,6 +53,7 @@ describe('useSignUp', () => {
it('calls refetchUser on successful sign-up', async () => {
vi.useFakeTimers();
const mockAddress = '0x123';
+ const mockTurnstileToken = '0x12345';
const mockChainId = 1;
const mockNonce = 'mock-nonce';
const mockRefetchUser = vi.fn();
@@ -69,13 +70,13 @@ describe('useSignUp', () => {
wrapper
});
- await act(() => result.current.mutate({ address: mockAddress }));
+ await act(() => result.current.mutate({ address: mockAddress, turnstileToken: mockTurnstileToken }));
vi.runAllTimers();
expect(apiClient.getNonce).toHaveBeenCalled();
expect(mockSignMessageAsync).toHaveBeenCalledWith({ message: 'Message for 0x123' });
- expect(apiClient.signUp).toHaveBeenCalledWith(expect.any(Object), 'mock-signature');
+ expect(apiClient.signUp).toHaveBeenCalledWith(expect.any(Object), mockTurnstileToken, 'mock-signature');
expect(mockRefetchUser).toHaveBeenCalled();
});
@@ -91,7 +92,7 @@ describe('useSignUp', () => {
wrapper
});
- await act(() => result.current.mutate({ address: mockAddress }));
+ await act(() => result.current.mutate({ address: mockAddress, turnstileToken: '' }));
expect(toast.error).toHaveBeenCalledWith('User rejected the request');
});
@@ -108,7 +109,7 @@ describe('useSignUp', () => {
wrapper
});
- await act(() => result.current.mutate({ address: mockAddress }));
+ await act(() => result.current.mutate({ address: mockAddress, turnstileToken: '' }));
expect(toast.error).toHaveBeenCalledWith('Network error');
});
diff --git a/apps/evm/src/hooks/useSignUp.ts b/apps/evm/src/hooks/useSignUp.ts
index 8c89505fc..694a03a90 100644
--- a/apps/evm/src/hooks/useSignUp.ts
+++ b/apps/evm/src/hooks/useSignUp.ts
@@ -12,7 +12,11 @@ import { useGetUser } from './useGetUser';
import { fusionKeys } from '@/lib/react-query';
import { apiClient } from '@/utils';
-const useSignUp = () => {
+type UseSignUpProps = {
+ onSuccess?: () => void;
+};
+
+const useSignUp = ({ onSuccess }: UseSignUpProps = {}) => {
const { signMessageAsync } = useSignMessage();
const { chain } = useAccount();
@@ -22,7 +26,14 @@ const useSignUp = () => {
return useMutation({
mutationKey: fusionKeys.signUp(),
- mutationFn: async ({ address }: { address: Address; referralCode?: string }) => {
+ mutationFn: async ({
+ address,
+ turnstileToken
+ }: {
+ address: Address;
+ turnstileToken: string;
+ referralCode?: string;
+ }) => {
const nonce = await apiClient.getNonce();
const message = new SiweMessage({
@@ -39,10 +50,11 @@ const useSignUp = () => {
message: message.prepareMessage()
});
- await apiClient.signUp(message, signature);
+ await apiClient.signUp(message, turnstileToken, signature);
},
onSuccess: (_, { address, referralCode }) => {
sendGAEvent('event', 'signup', { evm_address: JSON.stringify(address), referral_code: referralCode });
+ onSuccess?.();
setTimeout(() => refetchUser(), 100);
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
diff --git a/apps/evm/src/lib/store.ts b/apps/evm/src/lib/store.ts
index 990f489db..b80be8fe5 100644
--- a/apps/evm/src/lib/store.ts
+++ b/apps/evm/src/lib/store.ts
@@ -35,6 +35,11 @@ type SharedStore = {
};
};
};
+ turnstile: {
+ isOpen: boolean;
+ token?: string;
+ onSuccess?: (token: string) => void;
+ };
};
type BridgeStore = {
@@ -71,6 +76,9 @@ const store = new StoreLib({
type: undefined
}
}
+ },
+ turnstile: {
+ isOpen: false
}
},
bridge: {
diff --git a/apps/evm/src/locales/en.po b/apps/evm/src/locales/en.po
index 20b55a0e8..d1eaf9d99 100644
--- a/apps/evm/src/locales/en.po
+++ b/apps/evm/src/locales/en.po
@@ -446,7 +446,7 @@ msgstr "Close"
msgid "Collect Babylon Points on BOB"
msgstr "Collect Babylon Points on BOB"
-#: src/app/[lang]/sign-up/SignUp.tsx:107
+#: src/app/[lang]/sign-up/SignUp.tsx:140
msgid "Combining liquidity and security from Bitcoin and Ethereum. Mainnet live!"
msgstr "Combining liquidity and security from Bitcoin and Ethereum. Mainnet live!"
@@ -908,7 +908,7 @@ msgstr "If you already own BTC LSTs on other chains, you can bridge them over to
msgid "Input"
msgstr "Input"
-#: src/app/[lang]/sign-up/SignUp.tsx:116
+#: src/app/[lang]/sign-up/SignUp.tsx:149
msgid "Invalid referral code. You can try again, or proceed without one."
msgstr "Invalid referral code. You can try again, or proceed without one."
@@ -1290,7 +1290,7 @@ msgstr "Please note:"
msgid "Points"
msgstr "Points"
-#: src/app/[lang]/sign-up/SignUp.tsx:103
+#: src/app/[lang]/sign-up/SignUp.tsx:136
msgid "POWERED BY BTC & ETH"
msgstr "POWERED BY BTC & ETH"
@@ -1516,13 +1516,13 @@ msgstr "Solv XP"
#: src/app/[lang]/(bridge)/bridge/components/BridgeForm/BobBridgeForm.tsx:130
#: src/app/[lang]/fusion/components/LotterySections/LotteryModal/LotteryModal.tsx:60
#: src/hooks/useLogin.ts:50
-#: src/hooks/useSignUp.ts:53
+#: src/hooks/useSignUp.ts:65
msgid "Something went wrong. Please try again later."
msgstr "Something went wrong. Please try again later."
-#: src/app/[lang]/sign-up/SignUp.tsx:73
+#: src/app/[lang]/sign-up/SignUp.tsx:86
#: src/components/LoginButton/LoginButton.tsx:29
-#: src/components/SignUpButton/SignUpButton.tsx:29
+#: src/components/SignUpButton/SignUpButton.tsx:42
msgid "Something went wrong. Please try connecting your wallet again."
msgstr "Something went wrong. Please try connecting your wallet again."
@@ -1657,7 +1657,7 @@ msgstr "Start Harvesting"
#: src/app/[lang]/fusion/components/OpSuperuserModal/OpSuperuserModal.tsx:55
#: src/app/[lang]/fusion/components/UserInfo/UserInfo.tsx:376
-#: src/app/[lang]/sign-up/SignUp.tsx:128
+#: src/app/[lang]/sign-up/SignUp.tsx:161
msgid "Start Harvesting Spice"
msgstr "Start Harvesting Spice"
@@ -1771,7 +1771,7 @@ msgstr "The campaign will run until 1st February."
msgid "The final season"
msgstr "The final season"
-#: src/app/[lang]/sign-up/SignUp.tsx:100
+#: src/app/[lang]/sign-up/SignUp.tsx:133
msgid "THE FIRST HYBRID L2"
msgstr "THE FIRST HYBRID L2"
@@ -1983,7 +1983,7 @@ msgstr "Use your Spice total to support your favourite BOB builders. Winners wil
#: src/app/[lang]/(bridge)/bridge/components/BridgeForm/BobBridgeForm.tsx:128
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:96
#: src/hooks/useLogin.ts:48
-#: src/hooks/useSignUp.ts:51
+#: src/hooks/useSignUp.ts:63
msgid "User rejected the request"
msgstr "User rejected the request"
@@ -1999,6 +1999,10 @@ msgstr "Username"
msgid "Using the official bridge usually takes 7 days. For faster withdrawals we recommend using a 3rd party bridge for supported tokens (ETH, WBTC, USDT, USDC)."
msgstr "Using the official bridge usually takes 7 days. For faster withdrawals we recommend using a 3rd party bridge for supported tokens (ETH, WBTC, USDT, USDC)."
+#: src/components/TurnstileModal/TurnstileModal.tsx:23
+msgid "Verify you are human"
+msgstr "Verify you are human"
+
#: src/app/[lang]/(bridge)/components/TransactionList/TransactionList.tsx:133
#~ msgid "View All Transactions"
#~ msgstr "View All Transactions"
diff --git a/apps/evm/src/locales/zh.po b/apps/evm/src/locales/zh.po
index 2d7e220a9..036213326 100644
--- a/apps/evm/src/locales/zh.po
+++ b/apps/evm/src/locales/zh.po
@@ -544,7 +544,7 @@ msgstr ""
msgid "Collect Babylon Points on BOB"
msgstr ""
-#: src/app/[lang]/sign-up/SignUp.tsx:107
+#: src/app/[lang]/sign-up/SignUp.tsx:140
msgid "Combining liquidity and security from Bitcoin and Ethereum. Mainnet live!"
msgstr "结合比特币和以太坊的流动性和安全性。= 主网已上线!。"
@@ -1078,7 +1078,7 @@ msgstr ""
#~ msgid "Input Token"
#~ msgstr ""
-#: src/app/[lang]/sign-up/SignUp.tsx:116
+#: src/app/[lang]/sign-up/SignUp.tsx:149
msgid "Invalid referral code. You can try again, or proceed without one."
msgstr ""
@@ -1513,7 +1513,7 @@ msgstr "请注意:"
msgid "Points"
msgstr ""
-#: src/app/[lang]/sign-up/SignUp.tsx:103
+#: src/app/[lang]/sign-up/SignUp.tsx:136
msgid "POWERED BY BTC & ETH"
msgstr "比特币 + 以太坊共同驱动"
@@ -1760,13 +1760,13 @@ msgstr ""
#: src/app/[lang]/(bridge)/bridge/components/BridgeForm/BobBridgeForm.tsx:130
#: src/app/[lang]/fusion/components/LotterySections/LotteryModal/LotteryModal.tsx:60
#: src/hooks/useLogin.ts:50
-#: src/hooks/useSignUp.ts:53
+#: src/hooks/useSignUp.ts:65
msgid "Something went wrong. Please try again later."
msgstr ""
-#: src/app/[lang]/sign-up/SignUp.tsx:73
+#: src/app/[lang]/sign-up/SignUp.tsx:86
#: src/components/LoginButton/LoginButton.tsx:29
-#: src/components/SignUpButton/SignUpButton.tsx:29
+#: src/components/SignUpButton/SignUpButton.tsx:42
msgid "Something went wrong. Please try connecting your wallet again."
msgstr ""
@@ -1943,7 +1943,7 @@ msgstr "开始收获"
#: src/app/[lang]/fusion/components/OpSuperuserModal/OpSuperuserModal.tsx:55
#: src/app/[lang]/fusion/components/UserInfo/UserInfo.tsx:376
-#: src/app/[lang]/sign-up/SignUp.tsx:128
+#: src/app/[lang]/sign-up/SignUp.tsx:161
msgid "Start Harvesting Spice"
msgstr "开始收获Spice"
@@ -2089,7 +2089,7 @@ msgstr ""
msgid "The final season"
msgstr "最终季 - 不容错过!"
-#: src/app/[lang]/sign-up/SignUp.tsx:100
+#: src/app/[lang]/sign-up/SignUp.tsx:133
msgid "THE FIRST HYBRID L2"
msgstr "首个混合型二层"
@@ -2364,7 +2364,7 @@ msgstr "用你的Spice总数来支持你最喜爱的BOB构建者。获胜者将
#: src/app/[lang]/(bridge)/bridge/components/BridgeForm/BobBridgeForm.tsx:128
#: src/connect-ui/component/ConnectModal/ConnectModal.tsx:96
#: src/hooks/useLogin.ts:48
-#: src/hooks/useSignUp.ts:51
+#: src/hooks/useSignUp.ts:63
msgid "User rejected the request"
msgstr ""
@@ -2392,6 +2392,10 @@ msgstr ""
#~ msgid "Using the official bridge usually takes 7 days. For faster withdrawals we recommend using a 3rd Party bridge."
#~ msgstr ""
+#: src/components/TurnstileModal/TurnstileModal.tsx:23
+msgid "Verify you are human"
+msgstr ""
+
#: src/app/[lang]/wallet/Wallet.tsx:29
#~ msgid "View a summary of your wallet on the BOB network. DeFi positions may not be tracked."
#~ msgstr "查看您在 BOB 网络上的钱包概况。"
diff --git a/apps/evm/src/types/global.d.ts b/apps/evm/src/types/global.d.ts
index c488a4e6f..9854e6258 100644
--- a/apps/evm/src/types/global.d.ts
+++ b/apps/evm/src/types/global.d.ts
@@ -16,6 +16,7 @@ declare global {
NEXT_PUBLIC_GTM_ID: string;
NEXT_PUBLIC_GA_ID: string;
NEXT_PUBLIC_TRACES_SAMPLE_RATE: `${number}`;
+ NEXT_PUBLIC_TURNSTILE_SITE_KEY: string;
SENTRY_AUTH_TOKEN: string;
NEXT_PUBLIC_FEATURE_FLAG_OP_SUPERUSER: 'enabled' | 'disabled';
diff --git a/apps/evm/src/utils/api-client.ts b/apps/evm/src/utils/api-client.ts
index b81af1dab..42aefc6c1 100644
--- a/apps/evm/src/utils/api-client.ts
+++ b/apps/evm/src/utils/api-client.ts
@@ -445,14 +445,14 @@ class ApiClient {
return this.handleResponse(response);
}
- async signUp(message: SiweMessage, signature: Address) {
+ async signUp(message: SiweMessage, turnstileToken: string, signature: Address) {
const response = await fetch(`${this.baseUrl}/sign-up`, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
- body: JSON.stringify({ message, signature })
+ body: JSON.stringify({ message, signature, 'cf-turnstile-response': turnstileToken })
});
return this.handleResponse(response);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5ff078555..f190fe287 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -251,7 +251,7 @@ importers:
version: 7.6.19(bufferutil@4.0.8)(utf-8-validate@5.0.10)
turbo:
specifier: latest
- version: 2.3.3
+ version: 2.3.4
typescript:
specifier: 5.4.5
version: 5.4.5
@@ -481,6 +481,9 @@ importers:
'@lingui/react':
specifier: 'catalog:'
version: 4.12.0(react@18.3.1)
+ '@marsidev/react-turnstile':
+ specifier: ^1.1.0
+ version: 1.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@next/third-parties':
specifier: 'catalog:'
version: 15.0.4(next@14.2.15(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.44.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
@@ -2829,6 +2832,12 @@ packages:
'@lit/reactive-element@1.6.3':
resolution: {integrity: sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==}
+ '@marsidev/react-turnstile@1.1.0':
+ resolution: {integrity: sha512-X7bP9ZYutDd+E+klPYF+/BJHqEyyVkN4KKmZcNRr84zs3DcMoftlMAuoKqNSnqg0HE7NQ1844+TLFSJoztCdSA==}
+ peerDependencies:
+ react: ^18.2.0
+ react-dom: ^18.2.0
+
'@mdx-js/react@2.3.0':
resolution: {integrity: sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==}
peerDependencies:
@@ -12212,38 +12221,38 @@ packages:
tunnel-agent@0.6.0:
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
- turbo-darwin-64@2.3.3:
- resolution: {integrity: sha512-bxX82xe6du/3rPmm4aCC5RdEilIN99VUld4HkFQuw+mvFg6darNBuQxyWSHZTtc25XgYjQrjsV05888w1grpaA==}
+ turbo-darwin-64@2.3.4:
+ resolution: {integrity: sha512-uOi/cUIGQI7uakZygH+cZQ5D4w+aMLlVCN2KTGot+cmefatps2ZmRRufuHrEM0Rl63opdKD8/JIu+54s25qkfg==}
cpu: [x64]
os: [darwin]
- turbo-darwin-arm64@2.3.3:
- resolution: {integrity: sha512-DYbQwa3NsAuWkCUYVzfOUBbSUBVQzH5HWUFy2Kgi3fGjIWVZOFk86ss+xsWu//rlEAfYwEmopigsPYSmW4X15A==}
+ turbo-darwin-arm64@2.3.4:
+ resolution: {integrity: sha512-IIM1Lq5R+EGMtM1YFGl4x8Xkr0MWb4HvyU8N4LNoQ1Be5aycrOE+VVfH+cDg/Q4csn+8bxCOxhRp5KmUflrVTQ==}
cpu: [arm64]
os: [darwin]
- turbo-linux-64@2.3.3:
- resolution: {integrity: sha512-eHj9OIB0dFaP6BxB88jSuaCLsOQSYWBgmhy2ErCu6D2GG6xW3b6e2UWHl/1Ho9FsTg4uVgo4DB9wGsKa5erjUA==}
+ turbo-linux-64@2.3.4:
+ resolution: {integrity: sha512-1aD2EfR7NfjFXNH3mYU5gybLJEFi2IGOoKwoPLchAFRQ6OEJQj201/oNo9CDL75IIrQo64/NpEgVyZtoPlfhfA==}
cpu: [x64]
os: [linux]
- turbo-linux-arm64@2.3.3:
- resolution: {integrity: sha512-NmDE/NjZoDj1UWBhMtOPmqFLEBKhzGS61KObfrDEbXvU3lekwHeoPvAMfcovzswzch+kN2DrtbNIlz+/rp8OCg==}
+ turbo-linux-arm64@2.3.4:
+ resolution: {integrity: sha512-MxTpdKwxCaA5IlybPxgGLu54fT2svdqTIxRd0TQmpRJIjM0s4kbM+7YiLk0mOh6dGqlWPUsxz/A0Mkn8Xr5o7Q==}
cpu: [arm64]
os: [linux]
- turbo-windows-64@2.3.3:
- resolution: {integrity: sha512-O2+BS4QqjK3dOERscXqv7N2GXNcqHr9hXumkMxDj/oGx9oCatIwnnwx34UmzodloSnJpgSqjl8iRWiY65SmYoQ==}
+ turbo-windows-64@2.3.4:
+ resolution: {integrity: sha512-yyCrWqcRGu1AOOlrYzRnizEtdkqi+qKP0MW9dbk9OsMDXaOI5jlWtTY/AtWMkLw/czVJ7yS9Ex1vi9DB6YsFvw==}
cpu: [x64]
os: [win32]
- turbo-windows-arm64@2.3.3:
- resolution: {integrity: sha512-dW4ZK1r6XLPNYLIKjC4o87HxYidtRRcBeo/hZ9Wng2XM/MqqYkAyzJXJGgRMsc0MMEN9z4+ZIfnSNBrA0b08ag==}
+ turbo-windows-arm64@2.3.4:
+ resolution: {integrity: sha512-PggC3qH+njPfn1PDVwKrQvvQby8X09ufbqZ2Ha4uSu+5TvPorHHkAbZVHKYj2Y+tvVzxRzi4Sv6NdHXBS9Be5w==}
cpu: [arm64]
os: [win32]
- turbo@2.3.3:
- resolution: {integrity: sha512-DUHWQAcC8BTiUZDRzAYGvpSpGLiaOQPfYXlCieQbwUvmml/LRGIe3raKdrOPOoiX0DYlzxs2nH6BoWJoZrj8hA==}
+ turbo@2.3.4:
+ resolution: {integrity: sha512-1kiLO5C0Okh5ay1DbHsxkPsw9Sjsbjzm6cF85CpWjR0BIyBFNDbKqtUyqGADRS1dbbZoQanJZVj4MS5kk8J42Q==}
hasBin: true
tween-functions@1.2.0:
@@ -14381,7 +14390,7 @@ snapshots:
'@types/node': 20.5.1
chalk: 4.1.2
cosmiconfig: 8.3.6(typescript@5.4.5)
- cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.4.5))(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.4.5))(typescript@5.4.5)
+ cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.4.5))(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(typescript@5.4.5)
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
lodash.uniq: 4.5.0
@@ -15736,6 +15745,11 @@ snapshots:
dependencies:
'@lit-labs/ssr-dom-shim': 1.2.0
+ '@marsidev/react-turnstile@1.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
'@mdx-js/react@2.3.0(react@18.3.1)':
dependencies:
'@types/mdx': 2.0.13
@@ -22201,7 +22215,7 @@ snapshots:
core-util-is@1.0.3: {}
- cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.4.5))(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.4.5))(typescript@5.4.5):
+ cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.4.5))(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5))(typescript@5.4.5):
dependencies:
'@types/node': 20.5.1
cosmiconfig: 8.3.6(typescript@5.4.5)
@@ -23127,7 +23141,7 @@ snapshots:
'@typescript-eslint/parser': 7.13.0(eslint@8.57.0)(typescript@5.4.5)
eslint: 8.57.0
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0)
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0)
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0)
eslint-plugin-react: 7.34.2(eslint@8.57.0)
@@ -23151,13 +23165,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0):
+ eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.3.7(supports-color@8.1.1)
enhanced-resolve: 5.17.0
eslint: 8.57.0
- eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0)
+ eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
fast-glob: 3.3.2
get-tsconfig: 4.8.1
is-bun-module: 1.2.1
@@ -23170,14 +23184,14 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
- eslint-module-utils@2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0):
+ eslint-module-utils@2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0):
dependencies:
debug: 3.2.7(supports-color@8.1.1)
optionalDependencies:
'@typescript-eslint/parser': 7.13.0(eslint@8.57.0)(typescript@5.4.5)
eslint: 8.57.0
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0)
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0)
transitivePeerDependencies:
- supports-color
@@ -23191,7 +23205,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.0
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0)
+ eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.13.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
hasown: 2.0.2
is-core-module: 2.13.1
is-glob: 4.0.3
@@ -28501,32 +28515,32 @@ snapshots:
dependencies:
safe-buffer: 5.2.1
- turbo-darwin-64@2.3.3:
+ turbo-darwin-64@2.3.4:
optional: true
- turbo-darwin-arm64@2.3.3:
+ turbo-darwin-arm64@2.3.4:
optional: true
- turbo-linux-64@2.3.3:
+ turbo-linux-64@2.3.4:
optional: true
- turbo-linux-arm64@2.3.3:
+ turbo-linux-arm64@2.3.4:
optional: true
- turbo-windows-64@2.3.3:
+ turbo-windows-64@2.3.4:
optional: true
- turbo-windows-arm64@2.3.3:
+ turbo-windows-arm64@2.3.4:
optional: true
- turbo@2.3.3:
+ turbo@2.3.4:
optionalDependencies:
- turbo-darwin-64: 2.3.3
- turbo-darwin-arm64: 2.3.3
- turbo-linux-64: 2.3.3
- turbo-linux-arm64: 2.3.3
- turbo-windows-64: 2.3.3
- turbo-windows-arm64: 2.3.3
+ turbo-darwin-64: 2.3.4
+ turbo-darwin-arm64: 2.3.4
+ turbo-linux-64: 2.3.4
+ turbo-linux-arm64: 2.3.4
+ turbo-windows-64: 2.3.4
+ turbo-windows-arm64: 2.3.4
tween-functions@1.2.0: {}