@avalabs/avacloud-waas-react
Version:
React SDK for AvaCloud Wallet as a Service
447 lines (347 loc) • 11.6 kB
Markdown
# @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.
[](https://www.npmjs.com/package/@avalabs/avacloud-waas-react)
[](https://github.com/ava-labs/avacloud-waas-react/blob/main/LICENSE)
## Installation
```bash
# npm
npm install @avalabs/avacloud-waas-react
# yarn
yarn add @avalabs/avacloud-waas-react
# pnpm
pnpm add @avalabs/avacloud-waas-react
```
## Quick Start
Wrap your application with the `AvaCloudWalletProvider`:
```tsx
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:
```tsx
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.
```tsx
<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` | `'local' \| 'development' \| 'prod'` | Environment to use (default: `'prod'`) |
| `chainId` | `number` | EVM chain ID (default: `43113` - Avalanche Fuji Testnet) |
| `darkMode` | `boolean` | Enable dark mode for UI components (default: `false`) |
| `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 |
### UI Components
- `LoginButton`: Button component for initiating the login flow
- `WalletButton`: Button component for displaying wallet information and actions
- `WalletDisplay`: Component for displaying wallet address and balance
- `UserProfile`: Component for displaying user profile information
- `WalletCard`: Card component for displaying wallet information
- `TokensView`: Component for displaying token balances
- `SendView`: Component for sending tokens
- `ReceiveView`: Component for receiving tokens (displays QR code)
- `ExportView`: Component for exporting wallet information
## Hooks
### useAvaCloudWallet
The main hook for accessing wallet state and methods.
```tsx
const {
isAuthenticated,
isLoading,
user,
wallet,
login,
logout,
addAccount,
} = useAvaCloudWallet();
```
### useAuth
Simplified hook for basic authentication state.
```tsx
const { isAuthenticated, login, logout } = useAuth();
```
### useSignMessage
Hook for signing messages with the connected wallet.
```tsx
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.
```tsx
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.
```tsx
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.
```tsx
const { wallets, isLoading, error } = useUserWallets();
```
### useChainId
Hook for accessing and setting the current chain ID.
```tsx
const { chainId, setChainId } = useChainId();
```
### useGaslessTransaction
Hook for sending gasless (meta-)transactions through AvaCloud's gas relayer.
```tsx
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:
```bash
npm install wagmi viem@2.x @tanstack/react-query
```
### Setting up WAGMI with AvaCloud
```tsx
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:
```tsx
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 `AvaCloudWalletProvider` to 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:
```tsx
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:
```tsx
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](https://github.com/ava-labs/avacloud-waas-react/blob/main/CONTRIBUTING.md) for details.
## License
MIT © [Ava Labs, Inc.](https://github.com/ava-labs)