@b3dotfun/sdk 0.1.0-alpha.2 → 0.1.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,12 +5,23 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const chain_1 = require("../../../../anyspend/utils/chain");
6
6
  const token_1 = require("../../../../anyspend/utils/token");
7
7
  const react_1 = require("../../../../global-account/react");
8
+ const number_1 = require("../../../../shared/utils/number");
9
+ const react_2 = require("react");
8
10
  const viem_1 = require("viem");
9
11
  function TokenBalance({ token, walletAddress, onChangeInput, }) {
10
- const { rawBalance, formattedBalance, isLoading } = (0, react_1.useTokenBalanceDirect)({
11
- token,
12
- address: walletAddress,
13
- });
12
+ const tokenAddress = (0, token_1.isNativeToken)(token.address) ? "native" : token.address;
13
+ const { data, isLoading } = (0, react_1.useSimTokenBalance)(walletAddress, tokenAddress, token.chainId);
14
+ const { rawBalance, formattedBalance } = (0, react_2.useMemo)(() => {
15
+ const balance = data?.balances?.[0];
16
+ if (!balance?.amount) {
17
+ return { rawBalance: null, formattedBalance: "0" };
18
+ }
19
+ const raw = BigInt(balance.amount);
20
+ return {
21
+ rawBalance: raw,
22
+ formattedBalance: (0, number_1.formatTokenAmount)(raw, balance.decimals),
23
+ };
24
+ }, [data]);
14
25
  const handlePercentageClick = (percentage) => {
15
26
  if (!rawBalance)
16
27
  return;
@@ -30,7 +30,7 @@ export { useQueryBSMNT } from "./useQueryBSMNT";
30
30
  export { useRemoveSessionKey } from "./useRemoveSessionKey";
31
31
  export { useRouter } from "./useRouter";
32
32
  export { useSearchParamsSSR } from "./useSearchParamsSSR";
33
- export { useSimBalance, useSimSvmBalance } from "./useSimBalance";
33
+ export { useSimBalance, useSimSvmBalance, useSimTokenBalance } from "./useSimBalance";
34
34
  export { useSiwe } from "./useSiwe";
35
35
  export { useTokenBalance } from "./useTokenBalance";
36
36
  export { useTokenBalanceDirect } from "./useTokenBalanceDirect";
@@ -14,7 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.useUser = exports.useURLParams = exports.useUnifiedChainSwitchAndExecute = exports.useTurnkeyAuth = exports.useTokensFromAddress = exports.useTokenPriceWithFallback = exports.useTokenPrice = exports.useTokenFromUrl = exports.useTokenData = exports.useTokenBalancesByChain = exports.useTokenBalanceDirect = exports.useTokenBalance = exports.useSiwe = exports.useSimSvmBalance = exports.useSimBalance = exports.useSearchParamsSSR = exports.useRouter = exports.useRemoveSessionKey = exports.useQueryBSMNT = exports.useQueryB3 = exports.useProfileSettings = exports.useProfilePreference = exports.useProfile = exports.useDisplayName = exports.useOneBalance = exports.useNotifications = exports.useNativeBalanceFromRPC = exports.useNativeBalance = exports.useMediaQuery = exports.useIsomorphicLayoutEffect = exports.useIsMobile = exports.useHasMounted = exports.useHandleConnectWithPrivy = exports.useGlobalAccount = exports.useGetGeo = exports.useGetAllTWSigners = exports.useFirstEOA = exports.useExchangeRate = exports.useConnect = exports.useClient = exports.useChainSwitchWithAction = exports.useB3EnsName = exports.useB3BalanceFromAddresses = exports.useAuthentication = exports.useAuth = exports.useAnalytics = exports.useAddTWSessionKey = exports.useAccountWallet = exports.useAccountAssets = exports.createWagmiConfig = void 0;
17
+ exports.useURLParams = exports.useUnifiedChainSwitchAndExecute = exports.useTurnkeyAuth = exports.useTokensFromAddress = exports.useTokenPriceWithFallback = exports.useTokenPrice = exports.useTokenFromUrl = exports.useTokenData = exports.useTokenBalancesByChain = exports.useTokenBalanceDirect = exports.useTokenBalance = exports.useSiwe = exports.useSimTokenBalance = exports.useSimSvmBalance = exports.useSimBalance = exports.useSearchParamsSSR = exports.useRouter = exports.useRemoveSessionKey = exports.useQueryBSMNT = exports.useQueryB3 = exports.useProfileSettings = exports.useProfilePreference = exports.useProfile = exports.useDisplayName = exports.useOneBalance = exports.useNotifications = exports.useNativeBalanceFromRPC = exports.useNativeBalance = exports.useMediaQuery = exports.useIsomorphicLayoutEffect = exports.useIsMobile = exports.useHasMounted = exports.useHandleConnectWithPrivy = exports.useGlobalAccount = exports.useGetGeo = exports.useGetAllTWSigners = exports.useFirstEOA = exports.useExchangeRate = exports.useConnect = exports.useClient = exports.useChainSwitchWithAction = exports.useB3EnsName = exports.useB3BalanceFromAddresses = exports.useAuthentication = exports.useAuth = exports.useAnalytics = exports.useAddTWSessionKey = exports.useAccountWallet = exports.useAccountAssets = exports.createWagmiConfig = void 0;
18
+ exports.useUser = void 0;
18
19
  var createWagmiConfig_1 = require("../utils/createWagmiConfig");
19
20
  Object.defineProperty(exports, "createWagmiConfig", { enumerable: true, get: function () { return createWagmiConfig_1.createWagmiConfig; } });
20
21
  var useAccountAssets_1 = require("./useAccountAssets");
@@ -85,6 +86,7 @@ Object.defineProperty(exports, "useSearchParamsSSR", { enumerable: true, get: fu
85
86
  var useSimBalance_1 = require("./useSimBalance");
86
87
  Object.defineProperty(exports, "useSimBalance", { enumerable: true, get: function () { return useSimBalance_1.useSimBalance; } });
87
88
  Object.defineProperty(exports, "useSimSvmBalance", { enumerable: true, get: function () { return useSimBalance_1.useSimSvmBalance; } });
89
+ Object.defineProperty(exports, "useSimTokenBalance", { enumerable: true, get: function () { return useSimBalance_1.useSimTokenBalance; } });
88
90
  var useSiwe_1 = require("./useSiwe");
89
91
  Object.defineProperty(exports, "useSiwe", { enumerable: true, get: function () { return useSiwe_1.useSiwe; } });
90
92
  var useTokenBalance_1 = require("./useTokenBalance");
@@ -50,3 +50,10 @@ export interface SvmBalanceResponse {
50
50
  }
51
51
  export declare function useSimBalance(address?: string, chainIdsParam?: number[]): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
52
52
  export declare function useSimSvmBalance(address?: string, chains?: ("solana" | "eclipse")[], limit?: number): import("@tanstack/react-query").UseQueryResult<SvmBalanceResponse, Error>;
53
+ /**
54
+ * Hook to fetch a single token balance for a wallet.
55
+ * @param walletAddress - The wallet address to fetch balance for
56
+ * @param tokenAddress - The token contract address, or "native" for native token (ETH, etc.)
57
+ * @param chainId - Chain ID to query (defaults to 1 for Ethereum mainnet)
58
+ */
59
+ export declare function useSimTokenBalance(walletAddress?: string, tokenAddress?: string, chainId?: number): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useSimBalance = useSimBalance;
4
4
  exports.useSimSvmBalance = useSimSvmBalance;
5
+ exports.useSimTokenBalance = useSimTokenBalance;
5
6
  const react_query_1 = require("@tanstack/react-query");
6
7
  async function fetchSimBalance(address, chainIdsParam) {
7
8
  if (!address)
@@ -18,6 +19,24 @@ async function fetchSimBalance(address, chainIdsParam) {
18
19
  const balanceData = await response.json();
19
20
  return balanceData;
20
21
  }
22
+ async function fetchSimTokenBalance(walletAddress, tokenAddress, chainId) {
23
+ if (!walletAddress)
24
+ throw new Error("Wallet address is required");
25
+ if (!tokenAddress)
26
+ throw new Error("Token address is required");
27
+ if (!chainId)
28
+ throw new Error("Chain ID is required");
29
+ let url = `https://simdune-api.sean-430.workers.dev/?url=https://api.sim.dune.com/v1/evm/balances/${walletAddress}/token/${tokenAddress}?chain_ids=${chainId}`;
30
+ if (process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET) {
31
+ url += `&localkey=${process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET}`;
32
+ }
33
+ const response = await fetch(url);
34
+ if (!response.ok) {
35
+ throw new Error(`Failed to fetch token balance: ${response.statusText}`);
36
+ }
37
+ const balanceData = await response.json();
38
+ return balanceData;
39
+ }
21
40
  async function fetchSimSvmBalance(address, chains, limit) {
22
41
  if (!address)
23
42
  throw new Error("Address is required");
@@ -32,8 +51,8 @@ async function fetchSimSvmBalance(address, chains, limit) {
32
51
  if (queryParams.toString()) {
33
52
  url += `?${queryParams.toString()}`;
34
53
  }
35
- if (process.env.NEXT_PUBLIC_LOCAL_SIMDUNE_KEY) {
36
- url += `${queryParams.toString() ? "&" : "?"}localkey=${process.env.NEXT_PUBLIC_LOCAL_SIMDUNE_KEY}`;
54
+ if (process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET) {
55
+ url += `${queryParams.toString() ? "&" : "?"}localkey=${process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET}`;
37
56
  }
38
57
  const response = await fetch(url);
39
58
  if (!response.ok) {
@@ -64,3 +83,21 @@ function useSimSvmBalance(address, chains, limit) {
64
83
  enabled: Boolean(address),
65
84
  });
66
85
  }
86
+ /**
87
+ * Hook to fetch a single token balance for a wallet.
88
+ * @param walletAddress - The wallet address to fetch balance for
89
+ * @param tokenAddress - The token contract address, or "native" for native token (ETH, etc.)
90
+ * @param chainId - Chain ID to query (defaults to 1 for Ethereum mainnet)
91
+ */
92
+ function useSimTokenBalance(walletAddress, tokenAddress, chainId) {
93
+ return (0, react_query_1.useQuery)({
94
+ queryKey: ["simTokenBalance", walletAddress, tokenAddress, chainId],
95
+ queryFn: () => {
96
+ if (!walletAddress || !tokenAddress || !chainId) {
97
+ throw new Error("Missing required parameters");
98
+ }
99
+ return fetchSimTokenBalance(walletAddress, tokenAddress, chainId);
100
+ },
101
+ enabled: Boolean(walletAddress) && Boolean(tokenAddress),
102
+ });
103
+ }
@@ -1,13 +1,24 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { getNativeRequired } from "../../../../anyspend/utils/chain.js";
3
3
  import { isNativeToken } from "../../../../anyspend/utils/token.js";
4
- import { useTokenBalanceDirect } from "../../../../global-account/react/index.js";
4
+ import { useSimTokenBalance } from "../../../../global-account/react/index.js";
5
+ import { formatTokenAmount } from "../../../../shared/utils/number.js";
6
+ import { useMemo } from "react";
5
7
  import { formatUnits } from "viem";
6
8
  export function TokenBalance({ token, walletAddress, onChangeInput, }) {
7
- const { rawBalance, formattedBalance, isLoading } = useTokenBalanceDirect({
8
- token,
9
- address: walletAddress,
10
- });
9
+ const tokenAddress = isNativeToken(token.address) ? "native" : token.address;
10
+ const { data, isLoading } = useSimTokenBalance(walletAddress, tokenAddress, token.chainId);
11
+ const { rawBalance, formattedBalance } = useMemo(() => {
12
+ const balance = data?.balances?.[0];
13
+ if (!balance?.amount) {
14
+ return { rawBalance: null, formattedBalance: "0" };
15
+ }
16
+ const raw = BigInt(balance.amount);
17
+ return {
18
+ rawBalance: raw,
19
+ formattedBalance: formatTokenAmount(raw, balance.decimals),
20
+ };
21
+ }, [data]);
11
22
  const handlePercentageClick = (percentage) => {
12
23
  if (!rawBalance)
13
24
  return;
@@ -30,7 +30,7 @@ export { useQueryBSMNT } from "./useQueryBSMNT";
30
30
  export { useRemoveSessionKey } from "./useRemoveSessionKey";
31
31
  export { useRouter } from "./useRouter";
32
32
  export { useSearchParamsSSR } from "./useSearchParamsSSR";
33
- export { useSimBalance, useSimSvmBalance } from "./useSimBalance";
33
+ export { useSimBalance, useSimSvmBalance, useSimTokenBalance } from "./useSimBalance";
34
34
  export { useSiwe } from "./useSiwe";
35
35
  export { useTokenBalance } from "./useTokenBalance";
36
36
  export { useTokenBalanceDirect } from "./useTokenBalanceDirect";
@@ -30,7 +30,7 @@ export { useQueryBSMNT } from "./useQueryBSMNT.js";
30
30
  export { useRemoveSessionKey } from "./useRemoveSessionKey.js";
31
31
  export { useRouter } from "./useRouter.js";
32
32
  export { useSearchParamsSSR } from "./useSearchParamsSSR.js";
33
- export { useSimBalance, useSimSvmBalance } from "./useSimBalance.js";
33
+ export { useSimBalance, useSimSvmBalance, useSimTokenBalance } from "./useSimBalance.js";
34
34
  export { useSiwe } from "./useSiwe.js";
35
35
  export { useTokenBalance } from "./useTokenBalance.js";
36
36
  export { useTokenBalanceDirect } from "./useTokenBalanceDirect.js";
@@ -50,3 +50,10 @@ export interface SvmBalanceResponse {
50
50
  }
51
51
  export declare function useSimBalance(address?: string, chainIdsParam?: number[]): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
52
52
  export declare function useSimSvmBalance(address?: string, chains?: ("solana" | "eclipse")[], limit?: number): import("@tanstack/react-query").UseQueryResult<SvmBalanceResponse, Error>;
53
+ /**
54
+ * Hook to fetch a single token balance for a wallet.
55
+ * @param walletAddress - The wallet address to fetch balance for
56
+ * @param tokenAddress - The token contract address, or "native" for native token (ETH, etc.)
57
+ * @param chainId - Chain ID to query (defaults to 1 for Ethereum mainnet)
58
+ */
59
+ export declare function useSimTokenBalance(walletAddress?: string, tokenAddress?: string, chainId?: number): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
@@ -14,6 +14,24 @@ async function fetchSimBalance(address, chainIdsParam) {
14
14
  const balanceData = await response.json();
15
15
  return balanceData;
16
16
  }
17
+ async function fetchSimTokenBalance(walletAddress, tokenAddress, chainId) {
18
+ if (!walletAddress)
19
+ throw new Error("Wallet address is required");
20
+ if (!tokenAddress)
21
+ throw new Error("Token address is required");
22
+ if (!chainId)
23
+ throw new Error("Chain ID is required");
24
+ let url = `https://simdune-api.sean-430.workers.dev/?url=https://api.sim.dune.com/v1/evm/balances/${walletAddress}/token/${tokenAddress}?chain_ids=${chainId}`;
25
+ if (process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET) {
26
+ url += `&localkey=${process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET}`;
27
+ }
28
+ const response = await fetch(url);
29
+ if (!response.ok) {
30
+ throw new Error(`Failed to fetch token balance: ${response.statusText}`);
31
+ }
32
+ const balanceData = await response.json();
33
+ return balanceData;
34
+ }
17
35
  async function fetchSimSvmBalance(address, chains, limit) {
18
36
  if (!address)
19
37
  throw new Error("Address is required");
@@ -28,8 +46,8 @@ async function fetchSimSvmBalance(address, chains, limit) {
28
46
  if (queryParams.toString()) {
29
47
  url += `?${queryParams.toString()}`;
30
48
  }
31
- if (process.env.NEXT_PUBLIC_LOCAL_SIMDUNE_KEY) {
32
- url += `${queryParams.toString() ? "&" : "?"}localkey=${process.env.NEXT_PUBLIC_LOCAL_SIMDUNE_KEY}`;
49
+ if (process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET) {
50
+ url += `${queryParams.toString() ? "&" : "?"}localkey=${process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET}`;
33
51
  }
34
52
  const response = await fetch(url);
35
53
  if (!response.ok) {
@@ -60,3 +78,21 @@ export function useSimSvmBalance(address, chains, limit) {
60
78
  enabled: Boolean(address),
61
79
  });
62
80
  }
81
+ /**
82
+ * Hook to fetch a single token balance for a wallet.
83
+ * @param walletAddress - The wallet address to fetch balance for
84
+ * @param tokenAddress - The token contract address, or "native" for native token (ETH, etc.)
85
+ * @param chainId - Chain ID to query (defaults to 1 for Ethereum mainnet)
86
+ */
87
+ export function useSimTokenBalance(walletAddress, tokenAddress, chainId) {
88
+ return useQuery({
89
+ queryKey: ["simTokenBalance", walletAddress, tokenAddress, chainId],
90
+ queryFn: () => {
91
+ if (!walletAddress || !tokenAddress || !chainId) {
92
+ throw new Error("Missing required parameters");
93
+ }
94
+ return fetchSimTokenBalance(walletAddress, tokenAddress, chainId);
95
+ },
96
+ enabled: Boolean(walletAddress) && Boolean(tokenAddress),
97
+ });
98
+ }
@@ -30,7 +30,7 @@ export { useQueryBSMNT } from "./useQueryBSMNT";
30
30
  export { useRemoveSessionKey } from "./useRemoveSessionKey";
31
31
  export { useRouter } from "./useRouter";
32
32
  export { useSearchParamsSSR } from "./useSearchParamsSSR";
33
- export { useSimBalance, useSimSvmBalance } from "./useSimBalance";
33
+ export { useSimBalance, useSimSvmBalance, useSimTokenBalance } from "./useSimBalance";
34
34
  export { useSiwe } from "./useSiwe";
35
35
  export { useTokenBalance } from "./useTokenBalance";
36
36
  export { useTokenBalanceDirect } from "./useTokenBalanceDirect";
@@ -50,3 +50,10 @@ export interface SvmBalanceResponse {
50
50
  }
51
51
  export declare function useSimBalance(address?: string, chainIdsParam?: number[]): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
52
52
  export declare function useSimSvmBalance(address?: string, chains?: ("solana" | "eclipse")[], limit?: number): import("@tanstack/react-query").UseQueryResult<SvmBalanceResponse, Error>;
53
+ /**
54
+ * Hook to fetch a single token balance for a wallet.
55
+ * @param walletAddress - The wallet address to fetch balance for
56
+ * @param tokenAddress - The token contract address, or "native" for native token (ETH, etc.)
57
+ * @param chainId - Chain ID to query (defaults to 1 for Ethereum mainnet)
58
+ */
59
+ export declare function useSimTokenBalance(walletAddress?: string, tokenAddress?: string, chainId?: number): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.3",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -1,7 +1,9 @@
1
1
  import { components } from "@b3dotfun/sdk/anyspend/types/api";
2
2
  import { getNativeRequired } from "@b3dotfun/sdk/anyspend/utils/chain";
3
3
  import { isNativeToken } from "@b3dotfun/sdk/anyspend/utils/token";
4
- import { useTokenBalanceDirect } from "@b3dotfun/sdk/global-account/react";
4
+ import { useSimTokenBalance } from "@b3dotfun/sdk/global-account/react";
5
+ import { formatTokenAmount } from "@b3dotfun/sdk/shared/utils/number";
6
+ import { useMemo } from "react";
5
7
  import { formatUnits } from "viem";
6
8
 
7
9
  export function TokenBalance({
@@ -13,10 +15,20 @@ export function TokenBalance({
13
15
  walletAddress: string | undefined;
14
16
  onChangeInput: (value: string) => void;
15
17
  }) {
16
- const { rawBalance, formattedBalance, isLoading } = useTokenBalanceDirect({
17
- token,
18
- address: walletAddress,
19
- });
18
+ const tokenAddress = isNativeToken(token.address) ? "native" : token.address;
19
+ const { data, isLoading } = useSimTokenBalance(walletAddress, tokenAddress, token.chainId);
20
+
21
+ const { rawBalance, formattedBalance } = useMemo(() => {
22
+ const balance = data?.balances?.[0];
23
+ if (!balance?.amount) {
24
+ return { rawBalance: null, formattedBalance: "0" };
25
+ }
26
+ const raw = BigInt(balance.amount);
27
+ return {
28
+ rawBalance: raw,
29
+ formattedBalance: formatTokenAmount(raw, balance.decimals),
30
+ };
31
+ }, [data]);
20
32
 
21
33
  const handlePercentageClick = (percentage: number) => {
22
34
  if (!rawBalance) return;
@@ -39,7 +39,7 @@ export { useQueryBSMNT } from "./useQueryBSMNT";
39
39
  export { useRemoveSessionKey } from "./useRemoveSessionKey";
40
40
  export { useRouter } from "./useRouter";
41
41
  export { useSearchParamsSSR } from "./useSearchParamsSSR";
42
- export { useSimBalance, useSimSvmBalance } from "./useSimBalance";
42
+ export { useSimBalance, useSimSvmBalance, useSimTokenBalance } from "./useSimBalance";
43
43
  export { useSiwe } from "./useSiwe";
44
44
  export { useTokenBalance } from "./useTokenBalance";
45
45
  export { useTokenBalanceDirect } from "./useTokenBalanceDirect";
@@ -75,6 +75,30 @@ async function fetchSimBalance(address: string, chainIdsParam: number[]): Promis
75
75
  return balanceData;
76
76
  }
77
77
 
78
+ async function fetchSimTokenBalance(
79
+ walletAddress: string,
80
+ tokenAddress: string,
81
+ chainId: number,
82
+ ): Promise<SimBalanceResponse> {
83
+ if (!walletAddress) throw new Error("Wallet address is required");
84
+ if (!tokenAddress) throw new Error("Token address is required");
85
+ if (!chainId) throw new Error("Chain ID is required");
86
+
87
+ let url = `https://simdune-api.sean-430.workers.dev/?url=https://api.sim.dune.com/v1/evm/balances/${walletAddress}/token/${tokenAddress}?chain_ids=${chainId}`;
88
+ if (process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET) {
89
+ url += `&localkey=${process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET}`;
90
+ }
91
+
92
+ const response = await fetch(url);
93
+
94
+ if (!response.ok) {
95
+ throw new Error(`Failed to fetch token balance: ${response.statusText}`);
96
+ }
97
+
98
+ const balanceData: SimBalanceResponse = await response.json();
99
+ return balanceData;
100
+ }
101
+
78
102
  async function fetchSimSvmBalance(address: string, chains?: string[], limit?: number): Promise<SvmBalanceResponse> {
79
103
  if (!address) throw new Error("Address is required");
80
104
 
@@ -90,8 +114,8 @@ async function fetchSimSvmBalance(address: string, chains?: string[], limit?: nu
90
114
  if (queryParams.toString()) {
91
115
  url += `?${queryParams.toString()}`;
92
116
  }
93
- if (process.env.NEXT_PUBLIC_LOCAL_SIMDUNE_KEY) {
94
- url += `${queryParams.toString() ? "&" : "?"}localkey=${process.env.NEXT_PUBLIC_LOCAL_SIMDUNE_KEY}`;
117
+ if (process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET) {
118
+ url += `${queryParams.toString() ? "&" : "?"}localkey=${process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET}`;
95
119
  }
96
120
 
97
121
  const response = await fetch(url);
@@ -125,3 +149,22 @@ export function useSimSvmBalance(address?: string, chains?: ("solana" | "eclipse
125
149
  enabled: Boolean(address),
126
150
  });
127
151
  }
152
+
153
+ /**
154
+ * Hook to fetch a single token balance for a wallet.
155
+ * @param walletAddress - The wallet address to fetch balance for
156
+ * @param tokenAddress - The token contract address, or "native" for native token (ETH, etc.)
157
+ * @param chainId - Chain ID to query (defaults to 1 for Ethereum mainnet)
158
+ */
159
+ export function useSimTokenBalance(walletAddress?: string, tokenAddress?: string, chainId?: number) {
160
+ return useQuery({
161
+ queryKey: ["simTokenBalance", walletAddress, tokenAddress, chainId],
162
+ queryFn: () => {
163
+ if (!walletAddress || !tokenAddress || !chainId) {
164
+ throw new Error("Missing required parameters");
165
+ }
166
+ return fetchSimTokenBalance(walletAddress, tokenAddress, chainId);
167
+ },
168
+ enabled: Boolean(walletAddress) && Boolean(tokenAddress),
169
+ });
170
+ }