Skip to content

Commit 77e6ca3

Browse files
authored
Merge pull request #1080 from ionicprotocol/development
dev -> main
2 parents e53e306 + e70ef1d commit 77e6ca3

10 files changed

Lines changed: 238 additions & 114 deletions

File tree

packages/ui/.env.dist

Lines changed: 0 additions & 25 deletions
This file was deleted.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { NextResponse } from 'next/server';
2+
3+
import { getBaseRpcUrl } from '@ui/config/web3';
4+
5+
export async function GET() {
6+
const baseRpcUrl = getBaseRpcUrl();
7+
return NextResponse.json({ url: baseRpcUrl });
8+
}

packages/ui/app/layout.tsx

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { AppProgressBar as ProgressBar } from 'next-nprogress-bar';
99
import { Toaster } from 'react-hot-toast';
1010
import { WagmiProvider } from 'wagmi';
1111

12+
import BaseRpcProvider from '@ui/components/BaseRpcProvider';
1213
import Footer from '@ui/components/Footer';
1314
import Navbar from '@ui/components/Navbar';
1415
import { Toaster as ToastProvider } from '@ui/components/ui/toaster';
@@ -51,41 +52,43 @@ export default function RootLayout({
5152
<body className="scrollbar-hide font-inter">
5253
<WagmiProvider config={wagmiAdapter.wagmiConfig as any}>
5354
<QueryClientProvider client={queryClient}>
54-
<MultiIonicProvider>
55-
<Suspense fallback={<div>Loading...</div>}>
56-
<VeIONProvider>
57-
<TooltipProvider>
58-
<ProgressBar
59-
color="#3bff89ff"
60-
height="2px"
61-
options={{ showSpinner: false }}
62-
shallowRouting
63-
/>
64-
<div className="relative px-4 overflow-x-hidden pt-24 md:pt-[128px] pb-4 sm:pb-[300px] min-h-screen w-[100vw]">
65-
<Navbar />
66-
<main>{children}</main>
67-
<Footer />
68-
<ToastProvider />
69-
<Toaster
70-
toastOptions={{
71-
error: {
55+
<BaseRpcProvider>
56+
<MultiIonicProvider>
57+
<Suspense fallback={<div>Loading...</div>}>
58+
<VeIONProvider>
59+
<TooltipProvider>
60+
<ProgressBar
61+
color="#3bff89ff"
62+
height="2px"
63+
options={{ showSpinner: false }}
64+
shallowRouting
65+
/>
66+
<div className="relative px-4 overflow-x-hidden pt-24 md:pt-[128px] pb-4 sm:pb-[300px] min-h-screen w-[100vw]">
67+
<Navbar />
68+
<main>{children}</main>
69+
<Footer />
70+
<ToastProvider />
71+
<Toaster
72+
toastOptions={{
73+
error: {
74+
style: {
75+
background: '#e10000',
76+
color: '#fff'
77+
}
78+
},
79+
position: 'bottom-center',
7280
style: {
73-
background: '#e10000',
74-
color: '#fff'
81+
background: '#3bff89ff',
82+
color: '#000'
7583
}
76-
},
77-
position: 'bottom-center',
78-
style: {
79-
background: '#3bff89ff',
80-
color: '#000'
81-
}
82-
}}
83-
/>
84-
</div>
85-
</TooltipProvider>
86-
</VeIONProvider>
87-
</Suspense>
88-
</MultiIonicProvider>
84+
}}
85+
/>
86+
</div>
87+
</TooltipProvider>
88+
</VeIONProvider>
89+
</Suspense>
90+
</MultiIonicProvider>
91+
</BaseRpcProvider>
8992
</QueryClientProvider>
9093
</WagmiProvider>
9194
</body>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use client';
2+
3+
import { createContext, useContext } from 'react';
4+
5+
import { useBaseRpcUrl } from '@ui/hooks/useBaseRpcUrl';
6+
7+
type BaseRpcContextType = ReturnType<typeof useBaseRpcUrl> | undefined;
8+
9+
export const BaseRpcContext = createContext<BaseRpcContextType>(undefined);
10+
11+
export default function BaseRpcProvider({
12+
children
13+
}: {
14+
children: React.ReactNode;
15+
}) {
16+
const baseRpc = useBaseRpcUrl();
17+
18+
return (
19+
<BaseRpcContext.Provider value={baseRpc}>
20+
{children}
21+
</BaseRpcContext.Provider>
22+
);
23+
}
24+
25+
export function useBaseRpcContext() {
26+
return useContext(BaseRpcContext);
27+
}

packages/ui/config/web3.ts

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// config/web3.ts
22
import { createAppKit } from '@reown/appkit';
33
import {
4-
base,
54
optimism,
65
mode,
76
bob,
@@ -10,13 +9,32 @@ import {
109
superseed,
1110
worldchain,
1211
metalL2,
12+
base as baseNetwork,
1313
type AppKitNetwork
1414
} from '@reown/appkit/networks';
1515
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi';
1616
import { http } from 'viem';
1717

1818
import type { Transport } from 'viem';
1919

20+
export function getBaseRpcUrl(): string {
21+
if (typeof window === 'undefined' && process.env.BASE_RPC_URL) {
22+
return process.env.BASE_RPC_URL;
23+
}
24+
25+
return 'https://1rpc.io/base';
26+
}
27+
28+
const base: AppKitNetwork = {
29+
...baseNetwork,
30+
rpcUrls: {
31+
...baseNetwork.rpcUrls,
32+
default: {
33+
http: [getBaseRpcUrl()]
34+
}
35+
}
36+
};
37+
2038
export const ink: AppKitNetwork = {
2139
id: 57073,
2240
name: 'Ink',
@@ -152,10 +170,26 @@ const createChainTransport = (network: AppKitNetwork): Transport => {
152170
});
153171
};
154172

173+
const createBaseTransport = (): Transport => {
174+
return http(getBaseRpcUrl(), {
175+
timeout: 10_000,
176+
retryCount: 3,
177+
retryDelay: 1000,
178+
batch: {
179+
batchSize: 1024 * 1024,
180+
wait: 16
181+
}
182+
});
183+
};
184+
155185
// Create transports map with specific transport for each chain
156186
const transports = networks.reduce(
157187
(acc, network) => {
158-
acc[network.id as number] = createChainTransport(network);
188+
if (network.id === base.id) {
189+
acc[network.id as number] = createBaseTransport();
190+
} else {
191+
acc[network.id as number] = createChainTransport(network);
192+
}
159193
return acc;
160194
},
161195
{} as Record<number, Transport>

packages/ui/context/MultiIonicContext.tsx

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
import { useAccount, useDisconnect, useWalletClient } from 'wagmi';
2121

2222
import { MIDAS_LOCALSTORAGE_KEYS } from '@ui/constants/index';
23+
import { useBaseRpcUrl } from '@ui/hooks/useBaseRpcUrl';
2324
import { useEnabledChains } from '@ui/hooks/useChainConfig';
2425

2526
import { chainIdToConfig } from '@ionicprotocol/chains';
@@ -64,6 +65,8 @@ export const MultiIonicProvider = (
6465
const enabledChains = useEnabledChains();
6566
// const { chain, chains } = useNetwork();
6667
const { address: wagmiAddress, chain, isConnected } = useAccount();
68+
const baseRpc = useBaseRpcUrl();
69+
const base = baseRpc.baseChain;
6770

6871
// const { address, isConnecting, isReconnecting, isConnected } = useAccount();
6972
// const { isLoading: isNetworkLoading, isIdle, switchNetworkAsync } = useSwitchNetwork();
@@ -85,19 +88,24 @@ export const MultiIonicProvider = (
8588
const _securities: Security[] = [];
8689
const _chainIds: SupportedChains[] = [];
8790
enabledChains.map((chain) => {
88-
const config = chainIdToConfig[chain.id];
91+
const chainConfig = chainIdToConfig[chain.id];
8992
const _walletClient =
9093
chain.id === walletClient?.chain?.id ? walletClient : undefined;
94+
95+
const transportUrls =
96+
chain.id === 8453
97+
? [
98+
base.rpcUrls.default.http[0],
99+
...chainConfig.specificParams.metadata.rpcUrls.default.http
100+
]
101+
: chainConfig.specificParams.metadata.rpcUrls.default.http;
102+
91103
const client = createPublicClient({
92104
batch: { multicall: { wait: 16 } },
93105
chain,
94-
transport: fallback(
95-
config.specificParams.metadata.rpcUrls.default.http.map((url) =>
96-
http(url)
97-
)
98-
)
106+
transport: fallback(transportUrls.map((url) => http(url)))
99107
});
100-
_sdks.push(new IonicSdk(client as any, _walletClient, config));
108+
_sdks.push(new IonicSdk(client as any, _walletClient, chainConfig));
101109
// _securities.push(
102110
// new Security(
103111
// chain.id,
@@ -110,7 +118,7 @@ export const MultiIonicProvider = (
110118
});
111119

112120
return [_sdks, _securities, _chainIds.sort()];
113-
}, [enabledChains, walletClient]);
121+
}, [enabledChains, walletClient, base]);
114122

115123
const currentSdk = useMemo(() => {
116124
if (chain) {
@@ -144,18 +152,23 @@ export const MultiIonicProvider = (
144152
useEffect(() => {
145153
if (sdks.length > 0 && !walletClient) {
146154
sdks.map((sdk) => {
147-
const config = chainIdToConfig[sdk.chainId];
155+
const sdkConfig = chainIdToConfig[sdk.chainId];
156+
let rpcUrl = sdkConfig.specificParams.metadata.rpcUrls.default.http[0];
157+
158+
// Use custom RPC URL for Base
159+
if (sdk.chainId === 8453) {
160+
rpcUrl = base.rpcUrls.default.http[0];
161+
}
162+
148163
sdk.removeWalletClient(
149164
createPublicClient({
150165
chain,
151-
transport: http(
152-
config.specificParams.metadata.rpcUrls.default.http[0]
153-
)
166+
transport: http(rpcUrl)
154167
})
155168
);
156169
});
157170
}
158-
}, [walletClient, sdks, chain]);
171+
}, [walletClient, sdks, chain, base]);
159172

160173
useEffect(() => {
161174
if (wagmiAddress) {

packages/ui/hooks/rewards/useStakingRewards.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import { useMemo } from 'react';
2+
13
import { useQuery } from '@tanstack/react-query';
24
import { createPublicClient, http } from 'viem';
3-
import { base, mode, optimism } from 'viem/chains';
5+
import { mode, optimism } from 'viem/chains';
46
import { useAccount, useChainId, useWriteContract } from 'wagmi';
57

8+
import { useBaseRpcUrl } from '@ui/hooks/useBaseRpcUrl';
69
import { getStakingToContract } from '@ui/utils/getStakingTokens';
710
import { handleSwitchOriginChain } from '@ui/utils/NetworkChecker';
811

@@ -33,27 +36,34 @@ const veloAeroStakingStrategyAbi = [
3336
}
3437
] as const;
3538

36-
const publicClients = {
37-
[mode.id]: createPublicClient({
38-
chain: mode,
39-
transport: http()
40-
}),
41-
[base.id]: createPublicClient({
42-
chain: base,
43-
transport: http()
44-
})
45-
};
46-
4739
// Map chains to VeloAeroStakingStrategy addresses
4840
const veloAeroStakingStrategyAddresses: Record<number, `0x${string}`> = {
49-
[base.id]: '0x8b4352493077D2B04b033DE83516Dc2d53d09931',
41+
8453: '0x8b4352493077D2B04b033DE83516Dc2d53d09931', // Base chain ID
5042
[mode.id]: '0x8ff8b21a0736738b25597D32d8f7cf658f39f157'
5143
};
5244

5345
export const useStakingRewards = (chainId: number) => {
5446
const { address } = useAccount();
5547
const currentChainId = useChainId();
5648
const { writeContractAsync } = useWriteContract();
49+
const baseRpc = useBaseRpcUrl();
50+
51+
const base = baseRpc.baseChain;
52+
53+
const publicClient = useMemo(() => {
54+
if (chainId === 8453) {
55+
return createPublicClient({
56+
chain: base,
57+
transport: http(base.rpcUrls.default.http[0])
58+
});
59+
} else if (chainId === mode.id) {
60+
return createPublicClient({
61+
chain: mode,
62+
transport: http()
63+
});
64+
}
65+
return null;
66+
}, [chainId, base]);
5767

5868
const getTokenType = (chain: number) => {
5969
if (chain === mode.id) return 'mode';
@@ -68,7 +78,6 @@ export const useStakingRewards = (chainId: number) => {
6878
queryFn: async () => {
6979
if (!address) return null;
7080

71-
const publicClient = publicClients[chainId as keyof typeof publicClients];
7281
if (!publicClient) {
7382
console.error('No public client available for chain:', chainId);
7483
return null;
@@ -130,7 +139,6 @@ export const useStakingRewards = (chainId: number) => {
130139
queryFn: async () => {
131140
if (!address || !stakingWallet) return null;
132141

133-
const publicClient = publicClients[chainId as keyof typeof publicClients];
134142
if (!publicClient) {
135143
console.error('No public client available for chain:', chainId);
136144
return null;

0 commit comments

Comments
 (0)