Skip to content

Commit 1b815dc

Browse files
committed
refactor dynamic import for ens & sns
1 parent 3dd5cda commit 1b815dc

File tree

3 files changed

+79
-38
lines changed

3 files changed

+79
-38
lines changed

src/app/profile/edit/components/WalletLinkForm.tsx

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import { Input } from "@/components/ui/input";
55
import { Label } from "@/components/ui/label";
66
import { Button } from "@/components/ui/button";
77
import { Loader2, Info, Shield, ArrowRight } from "lucide-react";
8-
import { isAddress as isEvmAddress } from "viem"; // For ETH address validation
9-
import { normalize } from "viem/ens";
10-
import { viemClient } from "@/lib/walletLinking/viem";
8+
import {
9+
getViemClient,
10+
isAddress as isEvmAddressAsync,
11+
normalizeEns,
12+
} from "@/lib/walletLinking/viem";
1113
import { LinkedWallet } from "@/lib/walletLinking/readmeUtils";
1214
import { resolveSolDomain } from "@/lib/walletLinking/sns";
1315

@@ -51,19 +53,26 @@ export function WalletLinkForm({
5153
setEthAddress(ethWallet?.address || "");
5254
setSolAddress(solWallet?.address || "");
5355

54-
if (!ethWallet?.address || isEvmAddress(ethWallet.address)) {
55-
setIsEthValid(true);
56-
setEthAddressError("");
57-
} else {
58-
setIsEthValid(false);
59-
}
56+
// Validate initial addresses asynchronously
57+
const validateInitialAddresses = async () => {
58+
if (ethWallet?.address) {
59+
const isValid = await isEvmAddressAsync(ethWallet.address);
60+
setIsEthValid(isValid);
61+
if (!isValid) {
62+
setEthAddressError("Invalid Ethereum address");
63+
}
64+
}
6065

61-
if (!solWallet?.address || SOL_ADDRESS_REGEX.test(solWallet.address)) {
62-
setIsSolValid(true);
63-
setSolAddressError("");
64-
} else {
65-
setIsSolValid(false);
66-
}
66+
if (solWallet?.address) {
67+
const isValid = SOL_ADDRESS_REGEX.test(solWallet.address);
68+
setIsSolValid(isValid);
69+
if (!isValid) {
70+
setSolAddressError("Invalid Solana address");
71+
}
72+
}
73+
};
74+
75+
validateInitialAddresses();
6776
}, [wallets]);
6877

6978
useEffect(() => {
@@ -73,12 +82,16 @@ export function WalletLinkForm({
7382
return;
7483
}
7584

76-
const isEVMValid = isEvmAddress(ethAddress);
77-
const isENSValid = ENS_NAME_REGEX.test(ethAddress);
78-
setIsEthValid(isEVMValid || isENSValid);
79-
setEthAddressError(
80-
isEVMValid || isENSValid ? "" : "Invalid Ethereum address or ENS name.",
81-
);
85+
const validateEthAddress = async () => {
86+
const isEVMValid = await isEvmAddressAsync(ethAddress);
87+
const isENSValid = ENS_NAME_REGEX.test(ethAddress);
88+
setIsEthValid(isEVMValid || isENSValid);
89+
setEthAddressError(
90+
isEVMValid || isENSValid ? "" : "Invalid Ethereum address or ENS name.",
91+
);
92+
};
93+
94+
validateEthAddress();
8295
}, [ethAddress]);
8396

8497
useEffect(() => {
@@ -107,11 +120,13 @@ export function WalletLinkForm({
107120

108121
if (ethAddress) {
109122
const isENSValid = ENS_NAME_REGEX.test(ethAddress);
110-
const address = isENSValid
111-
? await viemClient.getEnsAddress({
112-
name: normalize(ethAddress),
113-
})
114-
: ethAddress;
123+
let address: string | null = ethAddress;
124+
125+
if (isENSValid) {
126+
const viemClient = await getViemClient();
127+
const normalizedName = await normalizeEns(ethAddress);
128+
address = await viemClient.getEnsAddress({ name: normalizedName });
129+
}
115130

116131
// If the address is not found, set the error and return
117132
if (!address) {

src/lib/walletLinking/sns.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import { Connection } from "@solana/web3.js";
2-
import { getDomainKeySync, NameRegistryState } from "@bonfida/spl-name-service";
3-
41
// Array of RPC endpoints to try in order
52
const RPC_ENDPOINTS = [
63
"https://api.mainnet-beta.solana.com", // Public Solana RPC
@@ -10,10 +7,13 @@ const RPC_ENDPOINTS = [
107

118
/**
129
* Gets the first working RPC endpoint by testing connectivity
10+
* @param Connection - The Solana Connection class from dynamic import
1311
* @returns Promise<string> The first working RPC endpoint URL
1412
* @throws Will throw an error if no endpoints are accessible
1513
*/
16-
async function getWorkingRpcEndpoint(): Promise<string> {
14+
async function getWorkingRpcEndpoint(
15+
Connection: typeof import("@solana/web3.js").Connection,
16+
): Promise<string> {
1717
for (const endpoint of RPC_ENDPOINTS) {
1818
try {
1919
const connection = new Connection(endpoint, "confirmed");
@@ -35,9 +35,16 @@ async function getWorkingRpcEndpoint(): Promise<string> {
3535
* @returns A Promise that resolves to the PublicKey of the domain owner
3636
* @throws Will throw an error if the domain doesn't exist or if there's a network issue
3737
*/
38-
export async function resolveSolDomain(domain: string) {
38+
export async function resolveSolDomain(domain: string): Promise<string | null> {
3939
try {
40-
const workingEndpoint = await getWorkingRpcEndpoint();
40+
// Import all Solana dependencies dynamically
41+
const [{ Connection }, { getDomainKeySync, NameRegistryState }] =
42+
await Promise.all([
43+
import("@solana/web3.js"),
44+
import("@bonfida/spl-name-service"),
45+
]);
46+
47+
const workingEndpoint = await getWorkingRpcEndpoint(Connection);
4148
const connection = new Connection(workingEndpoint);
4249

4350
const { pubkey } = getDomainKeySync(domain);

src/lib/walletLinking/viem.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
1-
import { createPublicClient, http } from "viem";
2-
import { mainnet } from "viem/chains";
1+
import type { PublicClient } from "viem";
32

4-
export const viemClient = createPublicClient({
5-
chain: mainnet,
6-
transport: http(),
7-
});
3+
let viemClient: PublicClient | null = null;
4+
5+
export async function getViemClient(): Promise<PublicClient> {
6+
if (!viemClient) {
7+
const { createPublicClient, http } = await import("viem");
8+
const { mainnet } = await import("viem/chains");
9+
10+
viemClient = createPublicClient({
11+
chain: mainnet,
12+
transport: http(),
13+
});
14+
}
15+
return viemClient;
16+
}
17+
18+
export async function isAddress(address: string): Promise<boolean> {
19+
const { isAddress } = await import("viem");
20+
return isAddress(address);
21+
}
22+
23+
export async function normalizeEns(name: string): Promise<string> {
24+
const { normalize } = await import("viem/ens");
25+
return normalize(name);
26+
}

0 commit comments

Comments
 (0)