Skip to content

Commit

Permalink
Merge pull request #322 from aptos-labs/aptos-connect-wallets-section
Browse files Browse the repository at this point in the history
Add Aptos Connect section to shadcn/ui wallet selector
  • Loading branch information
blakezimmerman authored Jun 14, 2024
2 parents 76d0e5a + 105c076 commit 535eafc
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changeset/good-goats-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aptos-labs/wallet-adapter-react": minor
---

Added `getAptosConnectWallets` utility function
5 changes: 5 additions & 0 deletions .changeset/tall-emus-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aptos-labs/wallet-adapter-core": minor
---

Added `APTOS_CONNECT_BASE_URL`, `APTOS_CONNECT_ACCOUNT_URL`, and `isAptosConnectWallet`
5 changes: 5 additions & 0 deletions .changeset/tall-needles-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aptos-labs/wallet-adapter-nextjs-example": minor
---

Moved Aptos Connect wallets to separate section in shadcn/ui wallet selector
102 changes: 82 additions & 20 deletions apps/nextjs-example/src/components/WalletSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
"use client";

import {
APTOS_CONNECT_ACCOUNT_URL,
AnyAptosWallet,
WalletItem,
getAptosConnectWallets,
isAptosConnectWallet,
isInstallRequired,
partitionWallets,
truncateAddress,
useWallet,
} from "@aptos-labs/wallet-adapter-react";
import { ChevronDown, Copy, LogOut } from "lucide-react";
import { ChevronDown, Copy, LogOut, User } from "lucide-react";
import { useCallback, useState } from "react";
import { Button } from "./ui/button";
import {
Expand All @@ -32,7 +35,7 @@ import {
import { useToast } from "./ui/use-toast";

export function WalletSelector() {
const { disconnect, account, connected } = useWallet();
const { account, connected, disconnect, wallet } = useWallet();
const { toast } = useToast();
const [isDialogOpen, setIsDialogOpen] = useState(false);

Expand Down Expand Up @@ -66,6 +69,18 @@ export function WalletSelector() {
<DropdownMenuItem onSelect={copyAddress} className="gap-2">
<Copy className="h-4 w-4" /> Copy address
</DropdownMenuItem>
{wallet && isAptosConnectWallet(wallet) && (
<DropdownMenuItem asChild>
<a
href={APTOS_CONNECT_ACCOUNT_URL}
target="_blank"
rel="noopener noreferrer"
className="flex gap-2"
>
<User className="h-4 w-4" /> Account
</a>
</DropdownMenuItem>
)}
<DropdownMenuItem onSelect={disconnect} className="gap-2">
<LogOut className="h-4 w-4" /> Disconnect
</DropdownMenuItem>
Expand All @@ -86,33 +101,67 @@ interface ConnectWalletDialogProps {
}

function ConnectWalletDialog({ close }: ConnectWalletDialogProps) {
const { wallets } = useWallet();
const { defaultWallets, moreWallets } = partitionWallets(wallets ?? []);
const { wallets = [] } = useWallet();

const {
/** Wallets that use social login to create an account on the blockchain */
aptosConnectWallets,
/** Wallets that use traditional wallet extensions */
otherWallets,
} = getAptosConnectWallets(wallets);

const {
/** Wallets that are currently installed or loadable. */
defaultWallets,
/** Wallets that are NOT currently installed or loadable. */
moreWallets,
} = partitionWallets(otherWallets);

return (
<DialogContent className="max-h-screen overflow-auto">
<DialogHeader>
<DialogTitle>Connect Wallet</DialogTitle>
<DialogHeader className="flex flex-col items-center">
<DialogTitle className="flex flex-col text-center leading-snug">
<span>Log in or sign up</span>
<span>with Social + Aptos Connect</span>
</DialogTitle>
</DialogHeader>
<div className="flex flex-col gap-3 pt-3">
{aptosConnectWallets.map((wallet) => (
<AptosConnectWalletRow
key={wallet.name}
wallet={wallet}
onConnect={close}
/>
))}
</div>
<div className="flex items-center gap-3 pt-4 text-muted-foreground">
<div className="h-px w-full bg-secondary" />
Or
<div className="h-px w-full bg-secondary" />
</div>
<div className="flex flex-col gap-3 pt-3">
{defaultWallets.map((wallet) => (
<WalletRow key={wallet.name} wallet={wallet} onConnect={close} />
))}
{!!moreWallets.length && (
<Collapsible className="flex flex-col gap-3">
<CollapsibleTrigger asChild>
<Button size="sm" variant="ghost" className="gap-2">
More wallets <ChevronDown />
</Button>
</CollapsibleTrigger>
<CollapsibleContent className="flex flex-col gap-3">
{moreWallets.map((wallet) => (
<WalletRow
key={wallet.name}
wallet={wallet}
onConnect={close}
/>
))}
</CollapsibleContent>
</Collapsible>
)}
</div>
{!!moreWallets.length && (
<Collapsible className="flex flex-col gap-4">
<CollapsibleTrigger asChild>
<Button size="sm" variant="ghost" className="gap-2">
More wallets <ChevronDown />
</Button>
</CollapsibleTrigger>
<CollapsibleContent className="flex flex-col gap-3">
{moreWallets.map((wallet) => (
<WalletRow key={wallet.name} wallet={wallet} onConnect={close} />
))}
</CollapsibleContent>
</Collapsible>
)}
</DialogContent>
);
}
Expand Down Expand Up @@ -145,3 +194,16 @@ function WalletRow({ wallet, onConnect }: WalletRowProps) {
</WalletItem>
);
}

function AptosConnectWalletRow({ wallet, onConnect }: WalletRowProps) {
return (
<WalletItem wallet={wallet} onConnect={onConnect}>
<WalletItem.ConnectButton asChild>
<Button size="lg" variant="outline" className="w-full gap-4">
<WalletItem.Icon className="h-5 w-5" />
<WalletItem.Name className="text-base font-normal" />
</Button>
</WalletItem.ConnectButton>
</WalletItem>
);
}
14 changes: 14 additions & 0 deletions packages/wallet-adapter-core/src/utils/aptosConnect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { WalletInfo } from "../LegacyWalletPlugins";
import { AnyAptosWallet } from "../WalletCore";

/** The base URL for all Aptos Connect wallets. */
export const APTOS_CONNECT_BASE_URL = "https://aptosconnect.app";

/** The URL to the Aptos Connect account page if the user is signed in to Aptos Connect. */
export const APTOS_CONNECT_ACCOUNT_URL =
"https://aptosconnect.app/dashboard/main-account";

/** Returns `true` if the provided wallet is an Aptos Connect wallet. */
export function isAptosConnectWallet(wallet: WalletInfo | AnyAptosWallet) {
return wallet.url.startsWith(APTOS_CONNECT_BASE_URL);
}
5 changes: 3 additions & 2 deletions packages/wallet-adapter-core/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { scopePollingDetectionStrategy } from "./scopePollingDetectionStrategy";
export * from "./localStorage";
export * from "./aptosConnect";
export * from "./helpers";
export * from "./localStorage";
export { scopePollingDetectionStrategy } from "./scopePollingDetectionStrategy";
11 changes: 11 additions & 0 deletions packages/wallet-adapter-react/src/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ export function isInstalledOrLoadable(wallet: AnyAptosWallet) {
);
}

/**
* Partitions the `wallets` array so that Aptos Connect wallets are grouped separately from the rest.
* Aptos Connect is a web wallet that uses social login to create accounts on the blockchain.
*/
export function getAptosConnectWallets(wallets: ReadonlyArray<AnyAptosWallet>) {
const { defaultWallets, moreWallets } = partitionWallets(wallets, (wallet) =>
wallet.url.includes("aptosconnect.app")
);
return { aptosConnectWallets: defaultWallets, otherWallets: moreWallets };
}

/**
* Returns true if the user is on desktop and the provided wallet requires installation of a browser extension.
* This can be used to decide whether to show a "Connect" button or "Install" link in the UI.
Expand Down

0 comments on commit 535eafc

Please sign in to comment.