@turnkey/react-wallet-kit
Version:
The easiest and most powerful way to integrate Turnkey's Embedded Wallets into your React applications.
234 lines (230 loc) • 9.44 kB
JavaScript
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var react = require('react');
var clsx = require('clsx');
var core = require('@turnkey/core');
var Hook = require('../../../providers/modal/Hook.js');
var Hook$1 = require('../../../providers/client/Hook.js');
var utils$1 = require('../../../utils/utils.js');
var WalletButton = require('./WalletButton.js');
var ExternalWalletChainSelector = require('./ExternalWalletChainSelector.js');
var WalletConnectFlow = require('./WalletConnectFlow.js');
var utils = require('./utils.js');
var Action = require('../Action.js');
var Success = require('../../design/Success.js');
var DisconnectWalletScreen = require('./DisconnectWalletScreen.js');
var base = require('../../../types/base.js');
function ExternalWalletSelector(props) {
const {
mode
} = props;
const {
pushPage,
popPage,
closeModal,
isMobile
} = Hook.useModal();
const {
walletProviders,
wallets,
loginOrSignupWithWallet,
connectWalletAccount,
disconnectWalletAccount
} = Hook$1.useTurnkey();
// Derive config based on mode
const isConnectMode = mode === base.WalletSelectorMode.Connect;
const sessionKey = isConnectMode ? undefined : props.sessionKey;
const shouldShowDisconnect = isConnectMode;
const successPageDuration = isConnectMode ? props.successPageDuration : undefined;
const onSuccess = isConnectMode ? props.onSuccess : undefined;
// Auth mode: show ActionPage and call loginOrSignupWithWallet
const handleAuthSelect = async provider => {
pushPage({
key: "Wallet Login/Signup",
content: jsxRuntime.jsx(Action.ActionPage, {
title: `Authenticating with ${provider.info.name}...`,
action: async () => {
await loginOrSignupWithWallet({
walletProvider: provider,
...(sessionKey && {
sessionKey
})
});
},
icon: jsxRuntime.jsx("img", {
className: "size-11 rounded-full",
src: provider.info.icon || ""
})
}),
showTitle: false
});
};
// Connect mode: show ActionPage, connect wallet, show success
const handleConnectSelect = async provider => {
pushPage({
key: `Connect ${provider.info.name}`,
content: jsxRuntime.jsx(Action.ActionPage, {
title: `Connecting ${provider.info.name}`,
icon: jsxRuntime.jsx("img", {
className: "size-11 rounded-full",
src: provider.info.icon || ""
}),
closeOnComplete: false,
action: async () => {
const account = await connectWalletAccount(provider);
onSuccess?.("connect", account);
if (successPageDuration && successPageDuration > 0) {
pushPage({
key: "Connecting Success",
content: jsxRuntime.jsx(Success.SuccessPage, {
text: "Successfully connected wallet!",
onComplete: () => closeModal(),
duration: successPageDuration
}),
preventBack: true,
showTitle: false
});
} else {
closeModal();
}
}
}),
showTitle: false
});
};
// Connect mode: show disconnect confirmation, then disconnect
const handleDisconnect = async provider => {
pushPage({
key: `Disconnect ${provider.info.name}`,
content: jsxRuntime.jsx(DisconnectWalletScreen.DisconnectWalletScreen, {
provider: provider,
onDisconnect: async () => {
const address = provider.connectedAddresses[0];
// Find the matching account from connected wallets
const connectedWallets = wallets.filter(w => w.source === core.WalletSource.Connected);
const matchedAccount = connectedWallets.flatMap(w => w.accounts).find(a => a.address === address);
await disconnectWalletAccount(provider);
onSuccess?.("disconnect", matchedAccount);
if (successPageDuration && successPageDuration > 0) {
pushPage({
key: "Disconnect Success",
content: jsxRuntime.jsx(Success.SuccessPage, {
text: "Successfully disconnected wallet!",
onComplete: () => closeModal(),
duration: successPageDuration
}),
preventBack: true,
showTitle: false
});
} else {
closeModal();
}
}
}),
showTitle: false
});
};
// Select the appropriate handler based on mode
const onSelect = isConnectMode ? handleConnectSelect : handleAuthSelect;
// Group providers by name
const grouped = walletProviders.reduce((acc, provider) => {
const name = provider.info.name;
if (!acc[name]) acc[name] = [];
acc[name].push(provider);
return acc;
}, {});
const pushStandardChainSelector = group => {
pushPage({
key: `Select chain`,
content: jsxRuntime.jsx(ExternalWalletChainSelector.ExternalWalletChainSelector, {
providers: group,
onSelect: onSelect,
onDisconnect: isConnectMode ? handleDisconnect : undefined
})
});
};
const pushWalletConnectFlow = group => {
pushPage({
key: "WalletConnect",
content: jsxRuntime.jsx(WalletConnectFlow.WalletConnectFlow, {
providers: group,
mode: mode,
sessionKey: sessionKey,
onDisconnect: isConnectMode ? handleDisconnect : undefined
}),
showTitle: false
});
};
// ─────────────────────────────────────────────────────────────────────────────
// Selection handlers
// ─────────────────────────────────────────────────────────────────────────────
const handleSelectGroup = group => {
const provider = group[0];
const isConnected = !!utils.canDisconnect(provider, shouldShowDisconnect);
// Single chain - direct action
if (group.length === 1) {
if (isConnected) {
handleDisconnect(provider);
} else {
onSelect(provider);
}
return;
}
// Multiple chains - need chain selector
if (utils$1.isWalletConnect(provider)) {
pushWalletConnectFlow(group);
} else {
pushStandardChainSelector(group);
}
};
// ─────────────────────────────────────────────────────────────────────────────
// Auto-navigation when only one provider group exists
// ─────────────────────────────────────────────────────────────────────────────
react.useEffect(() => {
const groupedValues = Object.values(grouped);
if (groupedValues.length === 1) {
popPage(); // Remove this page to prevent back-button loops
handleSelectGroup(groupedValues[0]);
}
}, [grouped]);
// ─────────────────────────────────────────────────────────────────────────────
// Render
// ─────────────────────────────────────────────────────────────────────────────
if (Object.keys(grouped).length === 0) {
return jsxRuntime.jsxs("div", {
className: clsx("flex flex-col h-40 mt-4 gap-2 justify-center items-center text-xs text-center text-icon-text-light dark:text-icon-text-dark", isMobile ? "w-full" : "w-80"),
children: [jsxRuntime.jsx("span", {
className: "text-sm font-medium",
children: "No wallet providers available."
}), jsxRuntime.jsx("span", {
children: "Only wallets supporting EIP-1193 (Ethereum) or the Solana wallet standard are supported."
})]
});
}
return jsxRuntime.jsx("div", {
className: clsx("min-h-42 max-h-64 mt-12 overflow-y-auto tk-scrollbar p-0.5", isMobile ? "w-full" : "w-80"),
children: jsxRuntime.jsx("div", {
className: "flex flex-col gap-2",
children: Object.entries(grouped).map(([name, group]) => {
const first = group[0];
return jsxRuntime.jsx(WalletButton.WalletButton, {
icon: first.info.icon ?? "",
name: first.info.name ?? "",
chains: group.map(c => ({
namespace: c.chainInfo.namespace,
isConnected: !!utils.canDisconnect(c, shouldShowDisconnect)
})),
onClick: () => handleSelectGroup(group),
shouldShowDisconnect: shouldShowDisconnect,
isMobile: isMobile
}, name);
})
})
});
}
Object.defineProperty(exports, "WalletSelectorMode", {
enumerable: true,
get: function () { return base.WalletSelectorMode; }
});
exports.ExternalWalletSelector = ExternalWalletSelector;
//# sourceMappingURL=ExternalWalletSelector.js.map