@avalabs/avacloud-waas-react
v1.4.1
Published
React SDK for AvaCloud Wallet as a Service
Readme
@avalabs/avacloud-waas-react
Official React SDK for AvaCloud Wallet-as-a-Service (WaaS) integration. This library provides a seamless way to integrate AvaCloud wallet functionality into your React applications.
Installation
# npm
npm install @avalabs/avacloud-waas-react
# yarn
yarn add @avalabs/avacloud-waas-react
# pnpm
pnpm add @avalabs/avacloud-waas-reactQuick Start
Wrap your application with the AvaCloudWalletProvider:
import { AvaCloudWalletProvider } from '@avalabs/avacloud-waas-react';
function App() {
return (
<AvaCloudWalletProvider
orgId="your-avacloud-org-id" // Required
chainId={43113} // Avalanche Fuji Testnet
>
<YourApp />
</AvaCloudWalletProvider>
);
}Use the wallet hooks and components in your application:
import { useAvaCloudWallet, LoginButton, WalletDisplay } from '@avalabs/avacloud-waas-react';
function YourComponent() {
const { isAuthenticated, isLoading, user, wallet } = useAvaCloudWallet();
if (isLoading) {
return <div>Loading...</div>;
}
return (
<div>
{isAuthenticated ? (
<>
<p>Welcome, {user?.email || 'User'}!</p>
<WalletDisplay />
</>
) : (
<LoginButton />
)}
</div>
);
}Core Components
AvaCloudWalletProvider
The main provider component that wraps your application and provides wallet context.
<AvaCloudWalletProvider
orgId="your-avacloud-org-id" // Required - your AvaCloud organization ID
chainId={43113} // Optional - defaults to Avalanche Fuji Testnet
darkMode={false} // Optional - theme mode for UI components
onAuthSuccess={(user) => console.log('Auth success', user)}
onAuthError={(error) => console.error('Auth error', error)}
onWalletUpdate={(wallet) => console.log('Wallet updated', wallet)}
>
{children}
</AvaCloudWalletProvider>Props
| Prop | Type | Description |
|------|------|-------------|
| orgId | string | Required - Your AvaCloud organization ID used to fetch wallet configuration |
| env | 'development' \| 'staging' \| 'production' | Environment to use (default: 'production') |
| chainId | number | EVM chain ID (default: 43113 - Avalanche Fuji Testnet) |
| darkMode | boolean | Enable dark mode for UI components (default: false) |
| authServiceUrl | string | Optional custom auth service URL. Overrides default environment-based URLs |
| onAuthSuccess | (user: Auth0User) => void | Callback on successful authentication |
| onAuthError | (error: Error) => void | Callback on authentication error |
| onWalletUpdate | (wallet: WalletInfo) => void | Callback when wallet information updates |
Configuring Auth Service URL
The auth service URL can be configured in three ways (in order of precedence):
Direct prop: Pass
authServiceUrldirectly to the provider<AvaCloudWalletProvider orgId="your-org-id" authServiceUrl="https://your-custom-auth-service.com" >Environment variable: Set
NEXT_PUBLIC_AUTH_SERVICE_URLin your.envfileNEXT_PUBLIC_AUTH_SERVICE_URL=https://your-custom-auth-service.comDefault URLs: Falls back to environment-based defaults
development:http://localhost:3000staging:https://ac-auth-service-env-staging-ava-labs.vercel.appproduction:https://ac-auth-service.vercel.app
UI Components
LoginButton: Button component for initiating the login flowWalletButton: Button component for displaying wallet information and actionsWalletDisplay: Component for displaying wallet address and balanceUserProfile: Component for displaying user profile informationWalletCard: Card component for displaying wallet informationTokensView: Component for displaying token balancesSendView: Component for sending tokensReceiveView: Component for receiving tokens (displays QR code)ExportView: Component for exporting wallet information
Hooks
useAvaCloudWallet
The main hook for accessing wallet state and methods.
const {
isAuthenticated,
isLoading,
user,
wallet,
login,
logout,
addAccount,
} = useAvaCloudWallet();useAuth
Simplified hook for basic authentication state.
const { isAuthenticated, login, logout } = useAuth();useSignMessage
Hook for signing messages with the connected wallet.
const { signMessage, isLoading, error } = useSignMessage();
const handleSign = async () => {
try {
const signature = await signMessage('Hello, AvaCloud!');
console.log('Signature:', signature);
} catch (error) {
console.error('Error signing message:', error);
}
};useSignTransaction
Hook for signing transactions with the connected wallet.
const { signTransaction, isLoading, error } = useSignTransaction();
const handleSignTx = async () => {
try {
const signedTx = await signTransaction({
to: '0x...',
value: '0.1',
data: '0x...',
});
console.log('Signed transaction:', signedTx);
} catch (error) {
console.error('Error signing transaction:', error);
}
};useTransferTokens
Hook for transferring tokens.
const { transfer, isLoading, error } = useTransferTokens();
const handleTransfer = async () => {
try {
const txHash = await transfer({
to: '0x...',
amount: '0.1',
tokenAddress: '0x...', // Optional, use null for native token
});
console.log('Transaction hash:', txHash);
} catch (error) {
console.error('Error transferring tokens:', error);
}
};useUserWallets
Hook for accessing and managing user wallets.
const { wallets, isLoading, error } = useUserWallets();useChainId
Hook for accessing and setting the current chain ID.
const { chainId, setChainId } = useChainId();useGaslessTransaction
Hook for sending gasless (meta-)transactions through AvaCloud's gas relayer.
import { useGaslessTransaction, useGlacier } from '@avalabs/avacloud-waas-react';
function CounterExample() {
// Retrieve the current subnet RPC URL from Glacier
const { blockchain } = useGlacier();
const gaslessConfig = {
relayerUrl: 'https://gas-relayer.avax-test.network/printedapr/testnet/rpc', // AvaCloud relayer RPC
subnetRpcUrl: blockchain?.rpcUrl || '', // Target subnet RPC
forwarderAddress: '0x52ec85e43d09889b2bf9e431935356e06f023680', // AvaCloud forwarder
domainName: 'Counter',
domainVersion: '1',
requestType: 'Message',
suffixType: 'bytes32', // Optional – request suffix type
suffixName: 'XMKUCJONOFSUSFCYHTYHCLX', // Optional – request suffix name
} as const;
// Counter contract information
const COUNTER_CONTRACT_ADDRESS = '0xe4bB5F15dc278197FcE9B21e5aC0442a95e25b5f';
const COUNTER_INCREMENT_ABI = [
{
inputs: [],
name: 'increment',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
] as const;
const {
sendGaslessTransaction,
isLoading,
error,
txHash,
reset,
} = useGaslessTransaction({
gaslessConfig,
contractAddress: COUNTER_CONTRACT_ADDRESS,
abi: COUNTER_INCREMENT_ABI,
});
const handleIncrement = () =>
sendGaslessTransaction({ functionName: 'increment' });
return (
<div>
<button onClick={handleIncrement} disabled={isLoading}>
Increment counter (no gas)
</button>
{isLoading && <p>Sending transaction…</p>}
{txHash && <p>Transaction hash: {txHash}</p>}
{error && <p style={{ color: 'red' }}>{error}</p>}
<button onClick={reset}>Reset</button>
</div>
);
}Parameters returned by the hook
| Property | Type | Description |
|----------|------|-------------|
| sendGaslessTransaction | (params: { functionName: string; args?: unknown[]; abi?: unknown; contractAddress?: string }) => Promise<void> | Sends the meta-transaction |
| isLoading | boolean | true while the transaction is being prepared or broadcast |
| error | string \| null | Error message, if any |
| txHash | string \| null | Transaction hash once broadcast |
| reset | () => void | Resets the hook state |
WAGMI Integration
This SDK includes a WAGMI connector that allows you to use AvaCloud wallets with WAGMI (React Ethereum Library).
Prerequisites
Install the required WAGMI dependencies:
npm install wagmi [email protected] @tanstack/react-querySetting up WAGMI with AvaCloud
import { WagmiProvider, createConfig } from 'wagmi';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { avaCloudWallet } from '@avalabs/avacloud-waas-react';
import { avalancheFuji } from 'wagmi/chains';
import { http } from 'wagmi';
const queryClient = new QueryClient();
const config = createConfig({
chains: [avalancheFuji],
connectors: [
avaCloudWallet(),
],
transports: {
[avalancheFuji.id]: http(),
},
});
function App() {
return (
<QueryClientProvider client={queryClient}>
<WagmiProvider config={config}>
<AvaCloudWalletProvider orgId="your-avacloud-org-id">
<YourApp />
</AvaCloudWalletProvider>
</WagmiProvider>
</QueryClientProvider>
);
}Using WAGMI Hooks
Once configured, use standard WAGMI hooks with your AvaCloud wallet:
import { useAccount, useConnect, useDisconnect, useSignMessage } from 'wagmi';
function WagmiExample() {
const { address, isConnected } = useAccount();
const { connect, connectors } = useConnect();
const { disconnect } = useDisconnect();
const { signMessage } = useSignMessage();
const handleConnect = () => {
const avaCloudConnector = connectors.find(c => c.id === 'avaCloudWallet');
if (avaCloudConnector) {
connect({ connector: avaCloudConnector });
}
};
const handleSign = async () => {
const signature = await signMessage({ message: 'Hello from WAGMI!' });
console.log('Signature:', signature);
};
return (
<div>
{isConnected ? (
<>
<p>Connected: {address}</p>
<button onClick={() => disconnect()}>Disconnect</button>
<button onClick={handleSign}>Sign Message</button>
</>
) : (
<button onClick={handleConnect}>Connect AvaCloud Wallet</button>
)}
</div>
);
}Important Notes
- The AvaCloud WAGMI connector requires the
AvaCloudWalletProviderto be present in your component tree - Authentication is still managed through the AvaCloud SDK's authentication flow
- The connector automatically syncs with the wallet state from
AvaCloudWalletProvider - All standard WAGMI hooks and functionality are supported
Advanced Usage
Theme Customization
Use the ThemeProvider to customize the appearance of UI components:
import { ThemeProvider } from '@avalabs/avacloud-waas-react';
function App() {
return (
<ThemeProvider darkMode={true}>
<YourApp />
</ThemeProvider>
);
}Custom Authentication Flow
You can implement a custom authentication flow using the lower-level hooks:
import { usePostMessage } from '@avalabs/avacloud-waas-react';
function CustomAuth() {
const { sendMessage, lastMessage } = usePostMessage();
const handleCustomLogin = () => {
sendMessage({
type: 'login',
payload: {
// Custom payload
}
});
};
// Handle response in useEffect
useEffect(() => {
if (lastMessage?.type === 'login_success') {
// Handle successful login
}
}, [lastMessage]);
return (
<button onClick={handleCustomLogin}>
Custom Login
</button>
);
}Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
Contributing
We welcome contributions! Please see CONTRIBUTING.md for details.
License
MIT © Ava Labs, Inc.
