This guide walks through a full Aurum integration in a client-side React app (Vite, Create React App, or any non-SSR React setup). For frameworks with server rendering, see the Next.js or TanStack Start guides.
Install
pnpm add @aurum-sdk/core @aurum-sdk/hooks
1. Create the Aurum instance
Put the instance in its own module so the entire app imports the same singleton.
import { Aurum } from '@aurum-sdk/core' ;
export const aurum = new Aurum ({
brand: { appName: 'My App' },
wallets: {
embedded: { projectId: import . meta . env . VITE_CDP_PROJECT_ID },
walletConnect: { projectId: import . meta . env . VITE_REOWN_PROJECT_ID },
},
});
new Aurum() is a singleton — calling it again returns the existing instance and warns if the config differs. Keep this file as the only place you construct it.
2. Wrap the app in AurumProvider
import React from 'react' ;
import ReactDOM from 'react-dom/client' ;
import { AurumProvider } from '@aurum-sdk/hooks' ;
import App from './App' ;
import { aurum } from './lib/aurum' ;
ReactDOM . createRoot ( document . getElementById ( 'root' ) ! ). render (
< React.StrictMode >
< AurumProvider aurum = { aurum } >
< App />
</ AurumProvider >
</ React.StrictMode > ,
);
useAccount exposes connection state (and rerenders on accountsChanged automatically). useConnect and useDisconnect trigger the modal flows.
src/components/ConnectButton.tsx
import { useAccount , useConnect , useDisconnect } from '@aurum-sdk/hooks' ;
export function ConnectButton () {
const { publicAddress , isConnected , isInitializing } = useAccount ();
const { connect , isPending , error } = useConnect ();
const { disconnect } = useDisconnect ();
if ( isInitializing ) return < button disabled > Loading... </ button > ;
if ( isConnected ) {
return (
< div >
< span > { publicAddress ?. slice ( 0 , 6 ) } … { publicAddress ?. slice ( - 4 ) } </ span >
< button onClick = { () => disconnect () } > Disconnect </ button >
</ div >
);
}
return (
<>
< button onClick = { () => connect () } disabled = { isPending } >
{ isPending ? 'Connecting...' : 'Connect Wallet' }
</ button >
{ error && < p role = "alert" > { error . message } </ p > }
</>
);
}
isInitializing is true while Aurum restores any persisted connection from the previous session. Always render a placeholder to avoid a flash of “disconnected” state on reload.
4. Sign a message
aurum.rpcProvider is EIP-1193 compatible — wire it into viem or ethers.
src/components/SignMessageButton.tsx
import { createWalletClient , custom } from 'viem' ;
import { useAccount } from '@aurum-sdk/hooks' ;
import { aurum } from '../lib/aurum' ;
const walletClient = createWalletClient ({
transport: custom ( aurum . rpcProvider ),
});
export function SignMessageButton () {
const { publicAddress , isConnected } = useAccount ();
async function signMessage () {
if ( ! publicAddress ) return ;
const signature = await walletClient . signMessage ({
account: publicAddress as `0x ${ string } ` ,
message: 'Hello from Aurum!' ,
});
console . log ( 'signature' , signature );
}
return (
< button onClick = { signMessage } disabled = { ! isConnected } >
Sign Message
</ button >
);
}
See the Viem , Ethers v5 , or Ethers v6 integration pages for the full surface (transactions, contract reads/writes).
5. Switch chains
src/components/SwitchChainButton.tsx
import { sepolia } from 'viem/chains' ;
import { useChain } from '@aurum-sdk/hooks' ;
export function SwitchChainButton () {
const { chainId , switchChain , error } = useChain ();
return (
<>
< p > Current chain: { chainId ?? 'not connected' } </ p >
< button onClick = { () => switchChain ( sepolia . id , sepolia ) } >
Switch to Sepolia
</ button >
{ error && < p role = "alert" > { error . message } </ p > }
</>
);
}
Pass the full Chain object so wallets that haven’t added it yet can prompt the user to do so.
Common patterns
Gate content behind a connection
import { useAccount } from '@aurum-sdk/hooks' ;
export function ProtectedRoute ({ children } : { children : React . ReactNode }) {
const { isConnected , isInitializing } = useAccount ();
if ( isInitializing ) return < div > Loading... </ div > ;
if ( ! isConnected ) return < div > Please connect your wallet to continue. </ div > ;
return <> { children } </> ;
}
Handle user-rejected and wallet-not-installed errors
import { UserRejectedError , WalletNotInstalledError } from '@aurum-sdk/core' ;
import { WalletId } from '@aurum-sdk/types' ;
import { useConnect } from '@aurum-sdk/hooks' ;
const { connect } = useConnect ();
try {
await connect ( WalletId . MetaMask );
} catch ( err ) {
if ( err instanceof UserRejectedError ) {
// user closed the modal — do nothing
} else if ( err instanceof WalletNotInstalledError ) {
alert ( ` ${ err . walletId } extension is not installed` );
} else {
throw err ;
}
}
See Errors for the full error class table.
Next steps
Customization Theme the modal
Headless mode Build a fully custom UI
React Hooks Hooks API reference