diff --git a/packages/panna-sdk/package.json b/packages/panna-sdk/package.json index 39272967..1e0971ae 100644 --- a/packages/panna-sdk/package.json +++ b/packages/panna-sdk/package.json @@ -59,6 +59,7 @@ "lru-cache": "^11.1.0", "lucide-react": "^0.514.0", "postcss": "^8.5.6", + "react-cookie": "^8.0.1", "react-hook-form": "^7.60.0", "tailwind-merge": "^3.3.1", "tailwindcss": "^4.1.11", diff --git a/packages/panna-sdk/src/core/auth/siwe-auth.ts b/packages/panna-sdk/src/core/auth/siwe-auth.ts index f2a74cf0..34774e3d 100644 --- a/packages/panna-sdk/src/core/auth/siwe-auth.ts +++ b/packages/panna-sdk/src/core/auth/siwe-auth.ts @@ -1,5 +1,6 @@ import type { Account } from 'thirdweb/wallets'; import Cookies from 'universal-cookie'; +import { authCookieOptions } from '../consts/cookies'; import { PannaApiService } from '../util/api-service'; import type { AuthChallengeReply, @@ -68,11 +69,7 @@ export class SiweAuth { this.pannaApiService = pannaApiService; // Cookie configuration for auth token storage // Using sameSite: 'strict' for CSRF protection, and secure: true to require HTTPS. - this.cookies = new Cookies(null, { - path: '/', - secure: true, - sameSite: 'strict' - }); + this.cookies = new Cookies(null, authCookieOptions); // Load existing auth data from cookies on initialization if (typeof window !== 'undefined') { diff --git a/packages/panna-sdk/src/core/consts/cookies.ts b/packages/panna-sdk/src/core/consts/cookies.ts new file mode 100644 index 00000000..d915a3e0 --- /dev/null +++ b/packages/panna-sdk/src/core/consts/cookies.ts @@ -0,0 +1,14 @@ +// For user preferences (long-lived) +export const preferenceCookieOptions = { + path: '/', + secure: true, + sameSite: 'strict', + maxAge: 60 * 60 * 24 * 365 // 1 year +} as const; + +// For auth tokens (session or short-lived) +export const authCookieOptions = { + path: '/', + secure: true, + sameSite: 'strict' +} as const; diff --git a/packages/panna-sdk/src/react/components/auth/connect-button.tsx b/packages/panna-sdk/src/react/components/auth/connect-button.tsx index 58a1dfc9..625dd80a 100644 --- a/packages/panna-sdk/src/react/components/auth/connect-button.tsx +++ b/packages/panna-sdk/src/react/components/auth/connect-button.tsx @@ -1,4 +1,6 @@ +import { CookiesProvider } from 'react-cookie'; import { useActiveAccount } from '@/hooks'; +import { preferenceCookieOptions } from '../../../core/consts/cookies'; import { AccountDialog } from '../account/account-dialog'; import { AccountViewProvider } from '../account/account-view-provider'; import { LoginButton } from './login-button'; @@ -64,7 +66,9 @@ export function ConnectButton({ <> {account?.address ? ( - + + + ) : ( ; }; +type CookieMap = { + panna_user_country: Country; +}; + export function SelectBuyRegionStep({ form }: SelectBuyRegionStepProps) { const { next } = useDialogStepper(); const [open, setOpen] = useState(false); const [query, setQuery] = useState(''); + const [cookie, setCookie] = useCookies<'panna_user_country', CookieMap>([ + 'panna_user_country' + ]); const countries = useMemo(() => { if (!query) return COUNTRIES_SORTED; @@ -55,16 +63,35 @@ export function SelectBuyRegionStep({ form }: SelectBuyRegionStepProps) { ? getCountryByCode(detectedCountryCode) : null; - // Set default country: detected > US > first available + // Set default country: cookie > (detected > US > first available) const defaultCountry = detectedCountry || getCountryByCode(DEFAULT_COUNTRY_CODE) || COUNTRIES_SORTED[0]; - if (defaultCountry) { + if (cookie.panna_user_country?.code) { + const cookieCountry = getCountryByCode(cookie.panna_user_country.code); + if (cookieCountry) { + form.setValue('country', cookieCountry); + } else if (defaultCountry) { + form.setValue('country', defaultCountry); + } + } else if (defaultCountry) { form.setValue('country', defaultCountry); } } - }, [form]); + }, [form, cookie.panna_user_country?.code]); + + const handleCountrySubmit = () => { + const selectedCountry = form.getValues('country'); + if (!selectedCountry) return; + if ( + !cookie.panna_user_country?.code || + cookie.panna_user_country.code !== selectedCountry.code + ) { + setCookie('panna_user_country', selectedCountry); + } + next(); + }; return (
@@ -142,7 +169,7 @@ export function SelectBuyRegionStep({ form }: SelectBuyRegionStepProps) { />