@stablecoin.xyz/react
Version:
React hooks and components for SBC Account Abstraction
831 lines (819 loc) • 31.1 kB
JavaScript
'use strict';
var react = require('react');
var jsxRuntime = require('react/jsx-runtime');
var core = require('@stablecoin.xyz/core');
const SbcContext = react.createContext(void 0);
function SbcProvider({ config, children, onError }) {
const [sbcAppKit, setSbcAppKit] = react.useState(null);
const [isInitialized, setIsInitialized] = react.useState(false);
const [error, setError] = react.useState(null);
const initialize = react.useCallback(async () => {
try {
setError(null);
setIsInitialized(false);
const appKit = new core.SbcAppKit(config);
setSbcAppKit(appKit);
setIsInitialized(true);
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Failed to initialize SBC App Kit");
if (config.debug) {
console.error("[SBC App Kit] Initialization failed:", error2);
console.error("[SBC App Kit] Config:", {
chain: config.chain?.name,
chainId: config.chain?.id,
wallet: config.wallet,
hasApiKey: !!config.apiKey,
apiKeyValid: config.apiKey?.startsWith("sbc-")
});
}
setError(error2);
setSbcAppKit(null);
setIsInitialized(false);
onError?.(error2);
}
}, [config, onError]);
react.useEffect(() => {
initialize();
}, [initialize]);
react.useEffect(() => {
return () => {
};
}, [sbcAppKit]);
const contextValue = {
sbcAppKit,
isInitialized,
error
};
return /* @__PURE__ */ jsxRuntime.jsx(SbcContext.Provider, { value: contextValue, children });
}
function useSbcContext() {
const context = react.useContext(SbcContext);
if (context === void 0) {
throw new Error("useSbcContext must be used within a SbcProvider");
}
return context;
}
function useSbcApp() {
const { sbcAppKit, isInitialized, error } = useSbcContext();
const [account, setAccount] = react.useState(null);
const [isLoadingAccount, setIsLoadingAccount] = react.useState(false);
const [accountError, setAccountError] = react.useState(null);
const [ownerAddress, setOwnerAddress] = react.useState(null);
const refreshAccount = react.useCallback(async () => {
if (!sbcAppKit || !isInitialized) {
setAccount(null);
setOwnerAddress(null);
return;
}
try {
setIsLoadingAccount(true);
setAccountError(null);
try {
const owner = sbcAppKit.getOwnerAddress();
setOwnerAddress(owner);
const accountInfo = await sbcAppKit.getAccount();
setAccount(accountInfo);
} catch (ownerError) {
setOwnerAddress(null);
setAccount(null);
return;
}
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Failed to load account");
if (sbcAppKit && sbcAppKit.debug) {
console.error("[SBC App Kit] Failed to load account:", error2);
}
setAccountError(error2);
setAccount(null);
setOwnerAddress(null);
} finally {
setIsLoadingAccount(false);
}
}, [sbcAppKit, isInitialized]);
const disconnectWallet = react.useCallback(() => {
if (sbcAppKit) {
try {
sbcAppKit.disconnectWallet();
} catch {
}
}
setAccount(null);
setOwnerAddress(null);
}, [sbcAppKit]);
react.useEffect(() => {
if (isInitialized && sbcAppKit) {
refreshAccount();
} else {
setAccount(null);
setAccountError(null);
setOwnerAddress(null);
}
}, [isInitialized, sbcAppKit, refreshAccount]);
return {
sbcAppKit,
isInitialized,
error,
account,
isLoadingAccount,
accountError,
refreshAccount,
ownerAddress,
disconnectWallet
};
}
function useUserOperation(options = {}) {
const { sbcAppKit, isInitialized } = useSbcContext();
const { refreshAccount } = useSbcApp();
const { onSuccess, onError, refreshAccount: shouldRefreshAccount = true } = options;
const [isLoading, setIsLoading] = react.useState(false);
const [isSuccess, setIsSuccess] = react.useState(false);
const [isError, setIsError] = react.useState(false);
const [error, setError] = react.useState(null);
const [data, setData] = react.useState(null);
const reset = react.useCallback(() => {
setIsLoading(false);
setIsSuccess(false);
setIsError(false);
setError(null);
setData(null);
}, []);
const sendUserOperation = react.useCallback(async (params) => {
if (!sbcAppKit || !isInitialized) {
const error2 = new Error("SBC App Kit is not initialized");
if (sbcAppKit && sbcAppKit.debug) {
console.error("[SBC App Kit] Cannot send user operation: SDK not initialized");
}
setError(error2);
setIsError(true);
onError?.(error2);
return;
}
try {
setIsLoading(true);
setIsError(false);
setError(null);
setIsSuccess(false);
const result = await sbcAppKit.sendUserOperation(params);
setData(result);
setIsSuccess(true);
onSuccess?.(result);
if (shouldRefreshAccount) {
refreshAccount();
}
return result;
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Failed to send user operation");
if (sbcAppKit.debug) {
console.error("[SBC App Kit] User operation failed:", error2);
console.error("[SBC App Kit] Params:", params);
}
setError(error2);
setIsError(true);
setData(null);
onError?.(error2);
return;
} finally {
setIsLoading(false);
}
}, [sbcAppKit, isInitialized, onSuccess, onError, shouldRefreshAccount, refreshAccount]);
const estimateUserOperation = react.useCallback(async (params) => {
if (!sbcAppKit || !isInitialized) {
const error2 = new Error("SBC App Kit is not initialized");
if (sbcAppKit && sbcAppKit.debug) {
console.error("[SBC App Kit] Cannot estimate user operation: SDK not initialized");
}
setError(error2);
setIsError(true);
onError?.(error2);
return;
}
try {
return await sbcAppKit.estimateUserOperation(params);
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Failed to estimate user operation");
if (sbcAppKit.debug) {
console.error("[SBC App Kit] Gas estimation failed:", error2);
console.error("[SBC App Kit] Params:", params);
}
setError(error2);
setIsError(true);
onError?.(error2);
return;
}
}, [sbcAppKit, isInitialized, onError]);
return {
sendUserOperation,
estimateUserOperation,
isLoading,
isSuccess,
isError,
error,
data,
reset
};
}
function useSbcDynamic(config) {
const [sbcAppKit, setSbcAppKit] = react.useState(null);
const [isInitialized, setIsInitialized] = react.useState(false);
const [error, setError] = react.useState(null);
const [account, setAccount] = react.useState(null);
const [isLoadingAccount, setIsLoadingAccount] = react.useState(false);
const [accountError, setAccountError] = react.useState(null);
const [ownerAddress, setOwnerAddress] = react.useState(null);
react.useEffect(() => {
const initializeSbc = async () => {
if (!config.primaryWallet?.address) {
setSbcAppKit(null);
setIsInitialized(false);
setError(null);
return;
}
try {
setError(null);
let dynamicWalletClient = null;
try {
dynamicWalletClient = await config.primaryWallet.connector.getWalletClient();
if (config.debug) {
console.log(`[useSbcDynamic] Dynamic wallet client obtained:`, {
hasClient: !!dynamicWalletClient,
walletAddress: config.primaryWallet.address
});
}
} catch (e) {
throw new Error(`Failed to get Dynamic wallet client: ${e instanceof Error ? e.message : "Unknown error"}`);
}
if (!dynamicWalletClient) {
throw new Error("Dynamic wallet client not available");
}
const sbcConfig = {
apiKey: config.apiKey,
chain: config.chain,
wallet: "dynamic",
walletOptions: {
dynamicContext: {
primaryWallet: config.primaryWallet
}
},
rpcUrl: config.rpcUrl,
debug: config.debug
};
const appKit = new core.SbcAppKit(sbcConfig);
await appKit.connectWallet("dynamic");
setSbcAppKit(appKit);
setIsInitialized(true);
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Failed to initialize SBC with Dynamic");
setError(error2);
setSbcAppKit(null);
setIsInitialized(false);
}
};
initializeSbc();
}, [config.primaryWallet?.address, config.apiKey, config.chain, config.rpcUrl, config.debug]);
const refreshAccount = react.useCallback(async () => {
if (!sbcAppKit || !isInitialized) {
setAccount(null);
setOwnerAddress(null);
return;
}
try {
setIsLoadingAccount(true);
setAccountError(null);
const owner = sbcAppKit.getOwnerAddress();
setOwnerAddress(owner);
const accountInfo = await sbcAppKit.getAccount();
setAccount(accountInfo);
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Failed to load account");
setAccountError(error2);
setAccount(null);
setOwnerAddress(null);
} finally {
setIsLoadingAccount(false);
}
}, [sbcAppKit, isInitialized]);
const disconnectWallet = react.useCallback(() => {
if (sbcAppKit) {
try {
sbcAppKit.disconnectWallet();
} catch {
}
}
setAccount(null);
setOwnerAddress(null);
}, [sbcAppKit]);
react.useEffect(() => {
if (isInitialized && sbcAppKit) {
refreshAccount();
} else {
setAccount(null);
setAccountError(null);
setOwnerAddress(null);
}
}, [isInitialized, sbcAppKit, refreshAccount]);
return {
sbcAppKit,
isInitialized,
error,
account,
isLoadingAccount,
accountError,
refreshAccount,
ownerAddress,
disconnectWallet
};
}
function useSbcPara(config) {
const [sbcAppKit, setSbcAppKit] = react.useState(null);
const [isInitialized, setIsInitialized] = react.useState(false);
const [error, setError] = react.useState(null);
const [account, setAccount] = react.useState(null);
const [isLoadingAccount, setIsLoadingAccount] = react.useState(false);
const [accountError, setAccountError] = react.useState(null);
const [ownerAddress, setOwnerAddress] = react.useState(null);
const isLoadingRef = react.useRef(false);
const { apiKey, chain, paraAccount, rpcUrl, debug = false, paraViemClients } = config;
const hasExternalWallet = paraAccount.isConnected && paraAccount.external?.evm?.address;
const hasEmbeddedWallet = paraAccount.isConnected && paraAccount.embedded?.wallets && paraAccount.embedded.wallets.length > 0;
react.useEffect(() => {
if (!paraAccount.isConnected || !hasExternalWallet && !hasEmbeddedWallet) {
setSbcAppKit(null);
setIsInitialized(false);
setOwnerAddress(null);
return;
}
const initializeSbc = async () => {
try {
setError(null);
if (debug) console.log("Initializing SBC with Para wallet...");
const paraWalletAddress = hasExternalWallet ? paraAccount.external?.evm?.address : hasEmbeddedWallet ? paraAccount.embedded.wallets?.[0]?.address : null;
if (!paraWalletAddress) {
throw new Error("No Para wallet address found");
}
if (!paraViemClients?.walletClient || !paraViemClients?.account) {
if (debug) console.log("[useSbcPara] Waiting for Para viem wallet client to be ready...");
return;
}
const appKit = new core.SbcAppKit({
apiKey,
chain,
walletClient: paraViemClients.walletClient,
rpcUrl,
debug
});
setSbcAppKit(appKit);
setOwnerAddress(paraWalletAddress);
setIsInitialized(true);
if (debug) console.log("SBC initialized and connected with Para wallet");
} catch (err) {
const errorMessage = err instanceof Error ? err.message : "Unknown error during SBC initialization";
if (debug) console.error("SBC initialization failed:", errorMessage);
setError(new Error(`SBC initialization failed: ${errorMessage}`));
setSbcAppKit(null);
setIsInitialized(false);
}
};
initializeSbc();
}, [apiKey, chain, rpcUrl, debug, paraAccount.isConnected, hasExternalWallet, hasEmbeddedWallet, paraViemClients?.walletClient, paraViemClients?.account]);
react.useEffect(() => {
if (!sbcAppKit || !isInitialized || isLoadingRef.current) {
return;
}
const loadAccount = async () => {
if (isLoadingRef.current) return;
isLoadingRef.current = true;
setIsLoadingAccount(true);
setAccountError(null);
try {
if (debug) console.log("Loading Para smart account...");
const accountInfo = await sbcAppKit.getAccount();
setAccount(accountInfo);
if (debug) console.log("Para smart account loaded:", accountInfo);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : "Unknown error loading account";
if (debug) console.error("Failed to load Para smart account:", errorMessage);
setAccountError(new Error(`Failed to load account: ${errorMessage}`));
} finally {
setIsLoadingAccount(false);
isLoadingRef.current = false;
}
};
loadAccount();
}, [sbcAppKit, isInitialized, debug]);
const refreshAccount = react.useCallback(async () => {
if (!sbcAppKit || isLoadingRef.current) return;
isLoadingRef.current = true;
setIsLoadingAccount(true);
setAccountError(null);
try {
if (debug) console.log("Refreshing Para smart account...");
const accountInfo = await sbcAppKit.getAccount();
setAccount(accountInfo);
if (debug) console.log("Para smart account refreshed:", accountInfo);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : "Unknown error refreshing account";
if (debug) console.error("Failed to refresh Para smart account:", errorMessage);
setAccountError(new Error(`Failed to refresh account: ${errorMessage}`));
} finally {
setIsLoadingAccount(false);
isLoadingRef.current = false;
}
}, [sbcAppKit, debug]);
const disconnectWallet = react.useCallback(async () => {
try {
if (debug) console.log("Cleaning up SBC integration...");
setSbcAppKit(null);
setIsInitialized(false);
setAccount(null);
setOwnerAddress(null);
setError(null);
setAccountError(null);
if (debug) console.log("SBC cleanup successful");
} catch (err) {
const errorMessage = err instanceof Error ? err.message : "Unknown error during cleanup";
if (debug) console.error("Failed to cleanup SBC:", errorMessage);
setError(new Error(`Failed to cleanup: ${errorMessage}`));
}
}, [debug]);
return {
sbcAppKit,
isInitialized,
error,
account,
isLoadingAccount,
accountError,
ownerAddress,
refreshAccount,
disconnectWallet
};
}
function useSbcTurnkey(config) {
const [sbcAppKit, setSbcAppKit] = react.useState(null);
const [isInitialized, setIsInitialized] = react.useState(false);
const [error, setError] = react.useState(null);
const [account, setAccount] = react.useState(null);
const [isLoadingAccount, setIsLoadingAccount] = react.useState(false);
const [accountError, setAccountError] = react.useState(null);
const [ownerAddress, setOwnerAddress] = react.useState(null);
react.useEffect(() => {
const initializeSbc = async () => {
const hasWalletClient = !!config.turnkeyWalletClient?.account?.address;
const hasTurnkeyClient = !!config.turnkeyClient;
if (!config.organizationId || !hasTurnkeyClient && !hasWalletClient) {
setSbcAppKit(null);
setIsInitialized(false);
setError(null);
return;
}
try {
setError(null);
if (config.debug) {
console.log("[useSbcTurnkey] Initializing SBC with Turnkey...", {
hasClient: !!config.turnkeyClient,
organizationId: config.organizationId,
hasWalletClient: !!config.turnkeyWalletClient
});
}
let walletAddress = null;
if (config.debug) {
console.log("[useSbcTurnkey] Checking for wallet address:", {
hasTurnkeyWalletClient: !!config.turnkeyWalletClient,
hasAccount: !!config.turnkeyWalletClient?.account,
hasAddress: !!config.turnkeyWalletClient?.account?.address,
address: config.turnkeyWalletClient?.account?.address
});
}
if (config.turnkeyWalletClient?.account?.address) {
walletAddress = config.turnkeyWalletClient.account.address;
if (config.debug) {
console.log("[useSbcTurnkey] Using address from wallet client:", walletAddress);
}
} else if (config.turnkeyClient) {
if (config.debug) {
console.log("[useSbcTurnkey] No wallet client address found, fetching from Turnkey...");
}
try {
const wallets = await config.turnkeyClient.getWallets({
organizationId: config.organizationId
});
const walletId = wallets?.wallets[0]?.walletId;
if (walletId) {
const accounts = await config.turnkeyClient.getWalletAccounts({
organizationId: config.organizationId,
walletId
});
walletAddress = accounts?.accounts[0]?.address;
}
} catch (e) {
throw new Error(`Failed to fetch Turnkey wallet info: ${e instanceof Error ? e.message : "Unknown error"}`);
}
}
if (!walletAddress) {
throw new Error("No Turnkey wallet address found. Create a wallet first or provide turnkeyWalletClient.");
}
const sbcConfig = {
apiKey: config.apiKey,
chain: config.chain,
wallet: "turnkey",
walletOptions: {
turnkeyContext: {
turnkeyClient: config.turnkeyClient,
organizationId: config.organizationId,
turnkeyWalletClient: config.turnkeyWalletClient
}
},
rpcUrl: config.rpcUrl,
debug: config.debug
};
const appKit = new core.SbcAppKit(sbcConfig);
await appKit.connectWallet("turnkey");
setSbcAppKit(appKit);
setOwnerAddress(walletAddress);
setIsInitialized(true);
if (config.debug) {
console.log("[useSbcTurnkey] SBC initialized successfully");
}
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Failed to initialize SBC with Turnkey");
setError(error2);
setSbcAppKit(null);
setIsInitialized(false);
if (config.debug) {
console.error("[useSbcTurnkey] Initialization failed:", error2);
}
}
};
initializeSbc();
}, [config.turnkeyClient, config.organizationId, config.apiKey, config.chain, config.rpcUrl, config.debug, config.turnkeyWalletClient]);
const refreshAccount = react.useCallback(async () => {
if (!sbcAppKit || !isInitialized) {
setAccount(null);
setOwnerAddress(null);
return;
}
try {
setIsLoadingAccount(true);
setAccountError(null);
const owner = sbcAppKit.getOwnerAddress();
setOwnerAddress(owner);
const accountInfo = await sbcAppKit.getAccount();
setAccount(accountInfo);
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Failed to load account");
setAccountError(error2);
setAccount(null);
setOwnerAddress(null);
} finally {
setIsLoadingAccount(false);
}
}, [sbcAppKit, isInitialized]);
const disconnectWallet = react.useCallback(() => {
if (sbcAppKit) {
try {
sbcAppKit.disconnectWallet();
} catch {
}
}
setAccount(null);
setOwnerAddress(null);
}, [sbcAppKit]);
react.useEffect(() => {
if (isInitialized && sbcAppKit) {
refreshAccount();
} else {
setAccount(null);
setAccountError(null);
setOwnerAddress(null);
}
}, [isInitialized, sbcAppKit, refreshAccount]);
return {
sbcAppKit,
isInitialized,
error,
account,
isLoadingAccount,
accountError,
refreshAccount,
ownerAddress,
disconnectWallet
};
}
function WalletConnect({ className, onConnectionChange }) {
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
padding: "12px 16px",
border: "1px solid #e0e0e0",
borderRadius: "8px",
textAlign: "center",
backgroundColor: "#f8f9fa"
}, children: [
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0 0 8px 0", fontSize: "14px", color: "#666" }, children: "\u{1F6A7} Wallet Connection Coming Soon" }),
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "12px", color: "#999" }, children: "This component will support multiple wallet providers and connection management." })
] }) });
}
function WalletButton({
walletType = "auto",
className = "",
onConnect,
onError,
children,
showLoading = true,
disabled = false,
render
}) {
const { sbcAppKit, refreshAccount } = useSbcApp();
const [isConnecting, setIsConnecting] = react.useState(false);
const [error, setError] = react.useState(null);
const handleConnect = async () => {
if (!sbcAppKit || isConnecting || disabled) return;
try {
setIsConnecting(true);
setError(null);
const result = await sbcAppKit.connectWallet(walletType);
await refreshAccount();
onConnect?.(result);
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Failed to connect wallet");
if (sbcAppKit.debug) {
console.error("[SBC App Kit] Wallet connection failed:", error2);
console.error("[SBC App Kit] Wallet type:", walletType);
}
setError(error2.message);
onError?.(error2);
} finally {
setIsConnecting(false);
}
};
const getButtonText = () => {
if (children) return children;
if (isConnecting) return "Connecting...";
if (walletType === "metamask") return "Connect MetaMask";
if (walletType === "coinbase") return "Connect Coinbase Wallet";
if (walletType === "walletconnect") return "Connect WalletConnect";
return "Connect Wallet";
};
const baseStyles = `
px-4 py-2 rounded-md font-medium transition-colors duration-200
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
disabled:opacity-50 disabled:cursor-not-allowed
`.trim();
const stateStyles = isConnecting || disabled ? "bg-gray-300 text-gray-600 cursor-not-allowed" : "bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800";
const finalClassName = `${baseStyles} ${stateStyles} ${className}`.trim();
if (render) {
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
render({
onClick: handleConnect,
isConnecting,
disabled: isConnecting || disabled || !sbcAppKit,
children: getButtonText(),
className: finalClassName
}),
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2", children: error })
] });
}
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
/* @__PURE__ */ jsxRuntime.jsxs(
"button",
{
type: "button",
className: finalClassName,
onClick: handleConnect,
disabled: isConnecting || disabled || !sbcAppKit,
children: [
showLoading && isConnecting && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block w-4 h-4 mr-2 animate-spin rounded-full border-2 border-transparent border-t-current" }),
getButtonText()
]
}
),
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2", children: error })
] });
}
function WalletSelector({
className = "",
onConnect,
onError,
showOnlyAvailable = true,
wallets: customWallets
}) {
const { sbcAppKit } = useSbcContext();
const [availableWallets, setAvailableWallets] = react.useState([]);
const [isLoading, setIsLoading] = react.useState(true);
const [connectingWallet, setConnectingWallet] = react.useState(null);
react.useEffect(() => {
const loadWallets = async () => {
if (!sbcAppKit) return;
try {
setIsLoading(true);
if (sbcAppKit.getAvailableWallets) {
const wallets = await sbcAppKit.getAvailableWallets();
setAvailableWallets(wallets);
} else {
const fallbackWallets = [
{
type: "metamask",
name: "MetaMask",
available: typeof window !== "undefined" && !!window.ethereum,
icon: "https://docs.metamask.io/img/metamask-fox.svg"
},
{
type: "coinbase",
name: "Coinbase Wallet",
available: typeof window !== "undefined" && !!(window.ethereum || window.coinbaseWalletExtension),
icon: "https://wallet-api-production.s3.amazonaws.com/uploads/tokens/eth_288.png"
},
{
type: "walletconnect",
name: "WalletConnect",
available: true,
icon: "https://registry.walletconnect.com/api/v1/logo/sm/walletconnect.png"
}
];
setAvailableWallets(fallbackWallets);
}
} catch (error) {
console.error("Failed to load available wallets:", error);
setAvailableWallets([]);
} finally {
setIsLoading(false);
}
};
loadWallets();
}, [sbcAppKit]);
const handleWalletConnect = async (walletType) => {
if (!sbcAppKit || connectingWallet) return;
try {
setConnectingWallet(walletType);
if (sbcAppKit.connectWallet) {
const result = await sbcAppKit.connectWallet(walletType);
onConnect?.(result);
} else {
throw new Error("Wallet integration coming soon! Use the dev:local script to test with the latest SDK features.");
}
} catch (err) {
const error = err instanceof Error ? err : new Error("Failed to connect wallet");
onError?.(error);
} finally {
setConnectingWallet(null);
}
};
const walletsToShow = customWallets || availableWallets;
const filteredWallets = showOnlyAvailable ? walletsToShow.filter((w) => w.available) : walletsToShow;
if (isLoading) {
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `space-y-4 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center text-gray-600", children: [
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-block w-6 h-6 animate-spin rounded-full border-2 border-gray-300 border-t-blue-600" }),
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2", children: "Detecting available wallets..." })
] }) });
}
if (filteredWallets.length === 0) {
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `text-center p-6 bg-gray-50 border border-gray-200 rounded-lg ${className}`, children: [
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 mb-4", children: "No compatible wallets found." }),
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "Please install MetaMask, Coinbase Wallet, or use WalletConnect to continue." })
] });
}
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `space-y-3 ${className}`, children: [
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-medium text-gray-900 mb-4", children: "Connect Wallet" }),
filteredWallets.map((wallet) => /* @__PURE__ */ jsxRuntime.jsxs(
"button",
{
type: "button",
className: `
w-full flex items-center justify-between p-4 border rounded-lg transition-colors
${wallet.available ? "border-gray-200 hover:border-blue-300 hover:bg-blue-50 focus:border-blue-500 focus:ring-2 focus:ring-blue-200" : "border-gray-100 bg-gray-50 cursor-not-allowed opacity-60"}
${connectingWallet === wallet.type ? "border-blue-500 bg-blue-50" : ""}
`,
onClick: () => handleWalletConnect(wallet.type),
disabled: !wallet.available || connectingWallet !== null,
children: [
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-3", children: [
wallet.icon && /* @__PURE__ */ jsxRuntime.jsx(
"img",
{
src: wallet.icon,
alt: `${wallet.name} icon`,
className: "w-8 h-8 rounded",
onError: (e) => {
e.target.style.display = "none";
}
}
),
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-left", children: [
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-gray-900", children: wallet.name }),
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: wallet.available ? "Ready to connect" : "Not installed" })
] })
] }),
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: connectingWallet === wallet.type ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-5 h-5 animate-spin rounded-full border-2 border-blue-600 border-t-transparent" }) : wallet.available ? /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5 text-gray-300", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })
]
},
wallet.type
))
] });
}
exports.SbcProvider = SbcProvider;
exports.WalletButton = WalletButton;
exports.WalletConnect = WalletConnect;
exports.WalletSelector = WalletSelector;
exports.useSbcApp = useSbcApp;
exports.useSbcContext = useSbcContext;
exports.useSbcDynamic = useSbcDynamic;
exports.useSbcPara = useSbcPara;
exports.useSbcTurnkey = useSbcTurnkey;
exports.useUserOperation = useUserOperation;