Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions demo/vue-app-new/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion demo/vue-app-new/src/components/AppSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from "../config";
import { formDataStore } from "../store/form";
import { getChainConfig } from "../utils/chainconfig";
import ExternalWalletOnlyTest from "./ExternalWalletOnlyTest.vue";

const formData = formDataStore;

Expand Down Expand Up @@ -170,6 +171,7 @@ const onSmartAccountChainChange = (chainIds: string[]) => {
<Tab v-if="formData.chainNamespaces.includes(CHAIN_NAMESPACES.EIP155)" variant="underline" :active="isActiveTab(4)" @click="onTabChange(4)">
Account Abstraction Provider
</Tab>
<Tab variant="underline" :active="isActiveTab(5)" @click="onTabChange(5)">External Wallet Only</Tab>
</Tabs>
<Card v-if="isActiveTab(0)" class="grid grid-cols-1 gap-2 px-4 py-4" :shadow="false">
<Select
Expand Down Expand Up @@ -501,7 +503,10 @@ const onSmartAccountChainChange = (chainIds: string[]) => {
/>
</Card>
</Card>
<div class="flex justify-center mt-5">
<Card v-if="isActiveTab(5)" class="px-4 py-4" :shadow="false">
<ExternalWalletOnlyTest />
</Card>
<div v-if="!isActiveTab(5)" class="flex justify-center mt-5">
<Button
v-if="formData.widget === 'modal'"
:class="['w-full !h-auto group py-3 rounded-full flex items-center justify-center']"
Expand Down
111 changes: 111 additions & 0 deletions demo/vue-app-new/src/components/ExternalWalletOnlyTest.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<script setup lang="ts">
import { Button, Card } from "@toruslabs/vue-components";
import { Web3Auth } from "@web3auth/modal";
import { CHAIN_NAMESPACES, WALLET_CONNECTORS } from "@web3auth/no-modal";
import { ref } from "vue";

const web3auth = ref<Web3Auth | null>(null);
const isConnected = ref(false);
const address = ref("");
const balance = ref("");
const connectorName = ref("");

const connect = async () => {
web3auth.value = new Web3Auth({
clientId: "BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ",
web3AuthNetwork: "sapphire_mainnet",
chains: [
{
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: "0x1",
rpcTarget: "https://rpc.ankr.com/eth",
displayName: "Ethereum Mainnet",
blockExplorerUrl: "https://etherscan.io",
ticker: "ETH",
tickerName: "Ethereum",
logo: "https://images.toruswallet.io/eth.svg",
},
],
multiInjectedProviderDiscovery: true,
modalConfig: {
hideWalletDiscovery: false,
connectors: {
[WALLET_CONNECTORS.AUTH]: {
label: "Auth",
showOnModal: false,
},
},
},
uiConfig: {
primaryButton: "externalLogin",
},
});

await web3auth.value.init();
const provider = await web3auth.value.connect();

if (provider) {
isConnected.value = true;
connectorName.value = web3auth.value.connectedConnectorName || "Unknown";

// Get address
const accounts = (await provider.request({ method: "eth_accounts" })) as string[];
address.value = accounts?.[0] || "";

// Get balance
if (address.value) {
const balanceHex = (await provider.request({
method: "eth_getBalance",
params: [address.value, "latest"],
})) as string;
const balanceWei = BigInt(balanceHex);
const balanceEth = Number(balanceWei) / 1e18;
balance.value = balanceEth.toFixed(4) + " ETH";
}
}
};

const disconnect = async () => {
if (web3auth.value) {
await web3auth.value.logout();
isConnected.value = false;
address.value = "";
balance.value = "";
connectorName.value = "";
web3auth.value = null;
}
};

const truncateAddress = (addr: string) => {
if (!addr) return "";
return `${addr.slice(0, 6)}...${addr.slice(-4)}`;
};
</script>

<template>
<div class="grid grid-cols-1 gap-2">
<!-- Connect Button -->
<div v-if="!isConnected">
<p class="text-sm text-app-gray-500 dark:text-app-gray-400 mb-3">
Test external wallet connection (isolated instance with AUTH hidden).
</p>
<Button block size="xs" pill @click="connect">Connect External Wallet Only</Button>
</div>

<!-- Dashboard after connection -->
<div v-else class="grid grid-cols-1 gap-2">
<Card class="px-4 py-4" :shadow="false">
<div class="mb-2 text-xl font-bold leading-tight text-left text-app-gray-900 dark:text-app-white">Connected Wallet</div>
<div class="grid grid-cols-2 gap-2 text-sm">
<div class="text-app-gray-500 dark:text-app-gray-400">Connector:</div>
<div class="font-medium text-app-gray-900 dark:text-app-white">{{ connectorName }}</div>
<div class="text-app-gray-500 dark:text-app-gray-400">Address:</div>
<div class="font-medium font-mono text-app-gray-900 dark:text-app-white">{{ truncateAddress(address) }}</div>
<div class="text-app-gray-500 dark:text-app-gray-400">Balance:</div>
<div class="font-medium text-app-gray-900 dark:text-app-white">{{ balance }}</div>
</div>
</Card>
<Button block size="xs" pill variant="tertiary" @click="disconnect">Disconnect</Button>
</div>
</div>
</template>
11 changes: 9 additions & 2 deletions packages/modal/src/ui/components/Loader/Loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,22 @@ function Loader(props: LoaderProps) {
[modalStatus, isConnectAndSignAuthenticationMode]
);

// Check if connector is an external wallet
const isExternalWallet = useMemo(() => {
return connector && externalWalletsConfig && connector in externalWalletsConfig;
}, [connector, externalWalletsConfig]);

useEffect(() => {
if (isConnectedAccordingToAuthenticationMode) {
// Skip success screen for external wallets, show for 1 second for social logins
const delay = isExternalWallet ? 0 : 1000;
const timeout = setTimeout(() => {
onClose();
}, 1000);
}, delay);

return () => clearTimeout(timeout);
}
}, [isConnectedAccordingToAuthenticationMode, onClose]);
}, [isConnectedAccordingToAuthenticationMode, isExternalWallet, onClose]);

return (
<div className="w3a--flex w3a--h-full w3a--flex-1 w3a--flex-col w3a--items-center w3a--justify-center w3a--gap-y-4">
Expand Down
40 changes: 21 additions & 19 deletions packages/modal/src/ui/components/Root/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -505,25 +505,27 @@ function Root(props: RootProps) {
/>
)}
{/* Connect Wallet Screen */}
{modalState.currentPage === PAGES.CONNECT_WALLET && !showExternalWalletPage && modalState.status === MODAL_STATUS.INITIALIZED && (
<ConnectWallet
isDark={isDark}
walletConnectUri={modalState.walletConnectUri}
metamaskConnectUri={modalState.metamaskConnectUri}
config={modalState.externalWalletsConfig}
walletRegistry={walletRegistry}
allRegistryButtons={allRegistryButtons}
connectorVisibilityMap={connectorVisibilityMap}
customConnectorButtons={customConnectorButtons}
deviceDetails={deviceDetails}
chainNamespace={chainNamespaces}
buttonRadius={buttonRadiusType}
handleWalletDetailsHeight={handleWalletDetailsHeight}
isExternalWalletModeOnly={isExternalWalletModeOnly}
onBackClick={onBackClick}
handleExternalWalletClick={preHandleExternalWalletClick}
/>
)}
{modalState.currentPage === PAGES.CONNECT_WALLET &&
(!showExternalWalletPage || isExternalWalletModeOnly) &&
modalState.status === MODAL_STATUS.INITIALIZED && (
<ConnectWallet
isDark={isDark}
walletConnectUri={modalState.walletConnectUri}
metamaskConnectUri={modalState.metamaskConnectUri}
config={modalState.externalWalletsConfig}
walletRegistry={walletRegistry}
allRegistryButtons={allRegistryButtons}
connectorVisibilityMap={connectorVisibilityMap}
customConnectorButtons={customConnectorButtons}
deviceDetails={deviceDetails}
chainNamespace={chainNamespaces}
buttonRadius={buttonRadiusType}
handleWalletDetailsHeight={handleWalletDetailsHeight}
isExternalWalletModeOnly={isExternalWalletModeOnly}
onBackClick={onBackClick}
handleExternalWalletClick={preHandleExternalWalletClick}
/>
)}
</>
)}
</>
Expand Down