Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit a162dda

Browse files
Fix geo blocking (#1450)
* fix: network env should come from a single source * feat: geo block BABY staking
1 parent c1d7065 commit a162dda

File tree

12 files changed

+65
-81
lines changed

12 files changed

+65
-81
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* @0xDazzer @jonybur @jeremy-babylonlabs @jrwbabylonlab @gbarkhatov
1+
* @jonybur @jeremy-babylonlabs @jrwbabylonlab @gbarkhatov

src/infrastructure/babylon.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { createLCDClient, txs, utils } from "@babylonlabs-io/babylon-proto-ts";
22

3-
import config from "./config";
3+
import { getNetworkConfigBBN } from "@/ui/common/config/network/bbn";
44

55
let clientInstance: Awaited<ReturnType<typeof createLCDClient>> | null = null;
66

77
export const getBabylonClient = async () => {
88
if (!clientInstance) {
9-
clientInstance = await createLCDClient({ url: config.babylon.lcdUrl });
9+
const networkConfig = getNetworkConfigBBN();
10+
clientInstance = await createLCDClient({ url: networkConfig.lcdUrl });
1011
}
1112
return clientInstance;
1213
};

src/infrastructure/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// TODO: Below config is not in use yet.
2+
// This is a placeholder for future code refactoring purposes.
13
export default {
24
api: {
35
baseUrl:

src/ui/baby/hooks/services/usePendingOperationsService.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
useState,
88
} from "react";
99

10+
import { network } from "@/ui/common/config/network/bbn";
1011
import { useCosmosWallet } from "@/ui/common/context/wallet/CosmosWalletProvider";
1112
import { useLogger } from "@/ui/common/hooks/useLogger";
1213

@@ -27,7 +28,7 @@ interface PendingOperationStorage {
2728
}
2829

2930
const getPendingOperationsKey = (walletAddress: string) =>
30-
`baby-pending-operations-${walletAddress}`;
31+
`baby-pending-operations-${network}-${walletAddress}`;
3132

3233
// Create the context
3334
const PendingOperationsContext = createContext<ReturnType<
@@ -167,13 +168,13 @@ function usePendingOperationsServiceInternal() {
167168
// Cleanup function to remove all pending operations from localStorage when epoch changes
168169
const cleanupAllPendingOperationsFromStorage = useCallback(() => {
169170
try {
170-
// Get all localStorage keys that match our pattern
171+
// Get all localStorage keys that match our pattern for the current network
171172
const allKeys = Object.keys(localStorage);
172173
const pendingOperationKeys = allKeys.filter((key) =>
173-
key.startsWith("baby-pending-operations-"),
174+
key.startsWith(`baby-pending-operations-${network}-`),
174175
);
175176

176-
// Remove all pending operations for all wallet addresses
177+
// Remove all pending operations for all wallet addresses on the current network
177178
pendingOperationKeys.forEach((storageKey) => {
178179
localStorage.removeItem(storageKey);
179180
});

src/ui/baby/layout.tsx

Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -23,41 +23,31 @@ import StakingForm from "./widgets/StakingForm";
2323
type TabId = "stake" | "activity" | "rewards";
2424

2525
export default function BabyLayout() {
26+
return (
27+
<PendingOperationsProvider>
28+
<BabyLayoutContent />
29+
</PendingOperationsProvider>
30+
);
31+
}
32+
33+
function BabyLayoutContent() {
2634
const [activeTab, setActiveTab] = useState<TabId>("stake");
2735
const { connected } = useWalletConnect();
2836
const { isGeoBlocked, isLoading } = useHealthCheck();
2937
const { bech32Address } = useCosmosWallet();
3038
const isConnected = connected && !isGeoBlocked && !isLoading;
39+
useEffect(() => {
40+
if (!connected) {
41+
setActiveTab("stake");
42+
}
43+
}, [connected]);
3144

32-
return (
33-
<PendingOperationsProvider>
34-
<BabyLayoutContent
35-
activeTab={activeTab}
36-
setActiveTab={setActiveTab}
37-
isConnected={isConnected}
38-
bech32Address={bech32Address}
39-
connected={connected}
40-
isGeoBlocked={isGeoBlocked}
41-
/>
42-
</PendingOperationsProvider>
43-
);
44-
}
45+
useEffect(() => {
46+
if (isGeoBlocked && (activeTab === "activity" || activeTab === "rewards")) {
47+
setActiveTab("stake");
48+
}
49+
}, [isGeoBlocked, activeTab]);
4550

46-
function BabyLayoutContent({
47-
activeTab,
48-
setActiveTab,
49-
isConnected,
50-
bech32Address,
51-
connected,
52-
isGeoBlocked,
53-
}: {
54-
activeTab: TabId;
55-
setActiveTab: (tab: TabId) => void;
56-
isConnected: boolean;
57-
bech32Address: string | undefined;
58-
connected: boolean;
59-
isGeoBlocked: boolean;
60-
}) {
6151
// Enable epoch polling to refetch delegations when epoch changes
6252
useEpochPolling(bech32Address);
6353

@@ -89,23 +79,11 @@ function BabyLayoutContent({
8979
);
9080
};
9181

92-
useEffect(() => {
93-
if (!connected) {
94-
setActiveTab("stake");
95-
}
96-
}, [connected, setActiveTab]);
97-
98-
useEffect(() => {
99-
if (isGeoBlocked && (activeTab === "activity" || activeTab === "rewards")) {
100-
setActiveTab("stake");
101-
}
102-
}, [isGeoBlocked, activeTab, setActiveTab]);
103-
10482
const tabItems = [
10583
{
10684
id: "stake",
10785
label: "Stake",
108-
content: <StakingForm />,
86+
content: <StakingForm isGeoBlocked={isGeoBlocked} />,
10987
},
11088
...(isConnected
11189
? [
@@ -131,7 +109,7 @@ function BabyLayoutContent({
131109
{
132110
id: "stake",
133111
label: "Stake",
134-
content: <StakingForm />,
112+
content: <StakingForm isGeoBlocked={isGeoBlocked} />,
135113
},
136114
];
137115

@@ -150,7 +128,7 @@ function BabyLayoutContent({
150128
<DelegationState>
151129
<RewardState>
152130
<Content>
153-
<AuthGuard fallback={fallbackContent}>
131+
<AuthGuard fallback={fallbackContent} geoBlocked={isGeoBlocked}>
154132
<Container
155133
as="main"
156134
className="flex flex-col gap-[3rem] pb-16 max-w-[760px] mx-auto flex-1"

src/ui/baby/widgets/StakingForm/index.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,21 @@ import { useStakingState } from "@/ui/baby/state/StakingState";
66
import { StakingModal } from "@/ui/baby/widgets/StakingModal";
77
import { SubmitButton } from "@/ui/baby/widgets/SubmitButton";
88
import { ValidatorField } from "@/ui/baby/widgets/ValidatorField";
9+
import { FormAlert } from "@/ui/common/components/Multistaking/MultistakingForm/FormAlert";
910

1011
interface FormFields {
1112
amount: number;
1213
validatorAddresses: string[];
1314
feeAmount: number;
1415
}
1516

16-
export default function StakingForm() {
17+
interface StakingFormProps {
18+
isGeoBlocked?: boolean;
19+
}
20+
21+
export default function StakingForm({
22+
isGeoBlocked = false,
23+
}: StakingFormProps) {
1724
const {
1825
loading,
1926
formSchema,
@@ -41,8 +48,9 @@ export default function StakingForm() {
4148
<ValidatorField />
4249
<FeeField babyPrice={babyPrice} calculateFee={calculateFee} />
4350

44-
<SubmitButton disabled={loading} />
51+
<SubmitButton disabled={loading} isGeoBlocked={isGeoBlocked} />
4552
<StakingModal />
53+
<FormAlert address={undefined} isGeoBlocked={isGeoBlocked} />
4654
</Form>
4755
);
4856
}

src/ui/baby/widgets/SubmitButton/index.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,28 @@ import { AuthGuard } from "@/ui/common/components/Common/AuthGuard";
66

77
interface SubmitButton {
88
disabled?: boolean;
9+
isGeoBlocked?: boolean;
910
onClick?: () => void;
1011
}
1112

12-
export function SubmitButton({ disabled = false, onClick }: SubmitButton) {
13+
export function SubmitButton({
14+
disabled = false,
15+
isGeoBlocked = false,
16+
onClick,
17+
}: SubmitButton) {
1318
const { isValid, errors } = useFormState();
1419
const { fields } = useStakingState();
1520
const errorField = fields.find((fieldName) => errors[fieldName]);
1621

1722
return (
18-
<AuthGuard fallback={<ConnectButton disabled={disabled} />}>
23+
<AuthGuard
24+
geoBlocked={isGeoBlocked}
25+
fallback={<ConnectButton disabled={disabled || isGeoBlocked} />}
26+
>
1927
<Button
2028
//@ts-expect-error - fix type issue in core-ui
2129
type="submit"
22-
disabled={!isValid || disabled}
30+
disabled={disabled || !isValid}
2331
className="w-full mt-2 capitalize disabled:!text-accent-primary disabled:!bg-accent-primary/10"
2432
onClick={onClick}
2533
>

src/ui/baby/widgets/ValidatorField/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export function ValidatorField() {
5959
return (
6060
<>
6161
<ListSubsection
62-
title="Selected Validator"
62+
title="Select Validator"
6363
max={1}
6464
items={selectedValidators}
6565
renderItem={(item) => <ValidatorItem name={item.name} />}

src/ui/common/components/Common/AuthGuard/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,18 @@ import { useAuthGuard } from "@/ui/common/hooks/useAuthGuard";
55
interface AuthGuardProps {
66
fallback?: ReactNode;
77
spinner?: ReactNode;
8+
geoBlocked?: boolean;
89
}
910

1011
export function AuthGuard({
1112
children,
1213
fallback,
1314
spinner,
15+
geoBlocked,
1416
}: PropsWithChildren<AuthGuardProps>) {
1517
const { connected, loading } = useAuthGuard();
1618

17-
if (!connected) {
19+
if (!connected || geoBlocked) {
1820
return loading ? spinner : fallback;
1921
}
2022

src/ui/common/components/Multistaking/MultistakingForm/FormAlert.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,17 @@ import { MdErrorOutline } from "react-icons/md";
22

33
import { Alert } from "@/ui/common/components/Alerts/Alert";
44
import { STAKING_DISABLED } from "@/ui/common/constants";
5+
import { GEO_BLOCK_MESSAGE } from "@/ui/common/types/services/healthCheck";
56

67
interface FormAlertProps {
78
address: string | undefined;
89
isGeoBlocked: boolean;
9-
geoBlockMessage: string | undefined;
1010
}
1111

12-
export const FormAlert = ({
13-
address,
14-
isGeoBlocked,
15-
geoBlockMessage,
16-
}: FormAlertProps) => {
12+
export const FormAlert = ({ address, isGeoBlocked }: FormAlertProps) => {
1713
const stakingDisabledMessage = (
1814
<>
19-
The Babylon network is temporarily halted. New stakes are paused until the
15+
The Babylon network is under maintenance. New stakes are paused until the
2016
network resumes.
2117
</>
2218
);
@@ -39,7 +35,7 @@ export const FormAlert = ({
3935
)
4036
}
4137
>
42-
{isGeoBlocked ? geoBlockMessage : stakingDisabledMessage}
38+
{isGeoBlocked ? GEO_BLOCK_MESSAGE : stakingDisabledMessage}
4339
</Alert>
4440
</div>
4541
);

0 commit comments

Comments
 (0)