Universal Wallet Adapter
While different wallets provide their own adapter SDKs, applications typically want to support multiple wallets to give users flexibility in choosing their preferred wallet. The Aleo community has developed an universal wallet adapter that is hosted here, which is largely based on Demox Labs' Leo Wallet Adapter.
This guide demonstrates how to implement the universal wallet adapter in React applications.
Installation
First, install the required packages:
npm install --save \
@demox-labs/aleo-wallet-adapter-base \
@demox-labs/aleo-wallet-adapter-react \
@demox-labs/aleo-wallet-adapter-reactui \
aleo-adapters
Setup
To use the wallet adapter, wrap your app with both WalletProvider
and WalletModalProvider
components. These provide the wallet functionality and UI context respectively.
The WalletProvider
accepts the following properties (wallets
is required):
export interface WalletProviderProps {
children: ReactNode;
wallets: Adapter[]; // Required
decryptPermission?: DecryptPermission;
programs?: string[];
network?: WalletAdapterNetwork;
autoConnect?: boolean;
onError?: (error: WalletError) => void;
localStorageKey?: string;
}
You can import DecryptPermission
and WalletAdapterNetwork
types from @demox-labs/aleo-wallet-adapter-base
.
Wallet Configuration
When creating wallet adapters, you can configure them with the following options:
export interface LeoWalletAdapterConfig {
appName?: string;
isMobile?: boolean;
mobileWebviewUrl?: string;
}
export interface FoxWalletAdapterConfig {
appName?: string;
isMobile?: boolean;
mobileWebviewUrl?: string;
}
export interface SoterWalletAdapterConfig {
appName?: string;
}
export interface PuzzleWalletAdapterConfig {
appName?: string;
appIconUrl?: string;
appDescription?: string;
programIdPermissions: Partial<Record<WalletAdapterNetwork, string[]>>;
}
Implementation Example
Here's a complete example showing how to set up the wallet adapter:
import { WalletModalProvider } from "@demox-labs/aleo-wallet-adapter-reactui";
import { WalletProvider } from "@demox-labs/aleo-wallet-adapter-react";
import { DecryptPermission, WalletAdapterNetwork } from "@demox-labs/aleo-wallet-adapter-base";
import { useMemo } from "react";
import {
PuzzleWalletAdapter,
LeoWalletAdapter,
FoxWalletAdapter,
SoterWalletAdapter
} from 'aleo-adapters';
export default function Providers({ children }: { children: React.ReactNode }) {
const wallets = useMemo(
() => [
new LeoWalletAdapter({
appName: 'Aleo app',
}),
new PuzzleWalletAdapter({
programIdPermissions: {
[WalletAdapterNetwork.MainnetBeta]: ['dApp_1.aleo', 'dApp_1_import.aleo', 'dApp_1_import_2.aleo'],
[WalletAdapterNetwork.TestnetBeta]: ['dApp_1_test.aleo', 'dApp_1_test_import.aleo', 'dApp_1_test_import_2.aleo']
},
appName: 'Aleo app',
appDescription: 'A privacy-focused DeFi app',
appIconUrl: ''
}),
new FoxWalletAdapter({
appName: 'Aleo app',
}),
new SoterWalletAdapter({
appName: 'Aleo app',
})
],
[]
);
return (
<WalletProvider
wallets={wallets}
decryptPermission={DecryptPermission.UponRequest}
network={WalletAdapterNetwork.MainnetBeta}
autoConnect
>
<WalletModalProvider>
{children}
</WalletModalProvider>
</WalletProvider>
);
}
Using the Wallet Button
Demox Labs provides a pre-built wallet button component that you can easily add to your application. To use it, import the WalletMultiButton
component from @demox-labs/aleo-wallet-adapter-reactui
along with its CSS styles.
import { WalletMultiButton } from "@demox-labs/aleo-wallet-adapter-reactui";
import "@demox-labs/aleo-wallet-adapter-reactui/dist/styles.css";
export default function WalletButton() {
return <WalletMultiButton />;
}
Using the Wallet Hook
Once user connected through the wallet button, you can use useWallet
hook from @demox-labs/aleo-wallet-adapter-react
to enable access to functions that helps connect and interact with the Aleo network. The hook provides the following interface:
export interface WalletContextState {
autoConnect: boolean;
wallets: Wallet[];
wallet: Wallet | null;
publicKey: string | null;
connecting: boolean;
connected: boolean;
disconnecting: boolean;
select(walletName: WalletName): void;
connect(decryptPermission: DecryptPermission, network: WalletAdapterNetwork, programs?: string[]): Promise<void>;
disconnect(): Promise<void>;
signMessage(message: Uint8Array): Promise<Uint8Array>;
decrypt(cipherText: string, tpk?: string, programId?: string, functionName?: string, index?: number): Promise<string>;
requestRecords(program: string): Promise<any[]>;
requestTransaction(transaction: AleoTransaction): Promise<string>;
requestExecution(transaction: AleoTransaction): Promise<string>;
requestBulkTransactions(transactions: AleoTransaction[]): Promise<string[]>;
requestDeploy(deployment: AleoDeployment): Promise<string>;
transactionStatus(transactionId: string): Promise<string>;
getExecution(transactionId: string): Promise<string>;
requestRecordPlaintexts(program: string): Promise<any[]>;
}
For detailed examples of using these methods, please refer to the Demox Labs Leo Wallet documentation.