Kuest uses Reown AppKit (formerly WalletConnect) to provide seamless wallet connectivity for Web3 users.
Supported wallets
MetaMask
Browser extension and mobile app
WalletConnect
200+ mobile wallets
Coinbase Wallet
Self-custody wallet
Safe (Gnosis)
Multi-sig smart contract wallets
Ledger
Hardware wallet support
Trust Wallet
Mobile-first wallet
AppKit configuration
Kuest’s wallet connection is configured in src/lib/appkit.ts:
import type { AppKitNetwork } from '@reown/appkit/networks'
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { polygonAmoy } from '@reown/appkit/networks'
export const projectId = process.env.REOWN_APPKIT_PROJECT_ID ?? ''
export const defaultNetwork = polygonAmoy
export const networks = [defaultNetwork] as [AppKitNetwork, ...AppKitNetwork[]]
export const wagmiAdapter = new WagmiAdapter({
ssr: false,
projectId,
networks,
})
export const wagmiConfig = wagmiAdapter.wagmiConfig
Wallet connection flow
User initiates connection
User clicks “Connect Wallet” button in the UI.
AppKit modal opens
Reown AppKit displays available wallet options.
Wallet authentication
User approves connection in their wallet app.
Network verification
System verifies user is on Polygon (or switches network).
Session creation
App creates authenticated session for trading.
Implementation example
import { useAppKit } from '@reown/appkit/react'
import { useAccount, useDisconnect } from 'wagmi'
export function ConnectWallet() {
const { open } = useAppKit()
const { address, isConnected } = useAccount()
const { disconnect } = useDisconnect()
if (isConnected) {
return (
<div>
<p>Connected: {address?.slice(0, 6)}...{address?.slice(-4)}</p>
<button onClick={() => disconnect()}>Disconnect</button>
</div>
)
}
return <button onClick={() => open()}>Connect Wallet</button>
}
Check network
import { useAccount, useSwitchChain } from 'wagmi'
import { polygonAmoy } from 'wagmi/chains'
function NetworkGuard({ children }: { children: React.ReactNode }) {
const { chain } = useAccount()
const { switchChain } = useSwitchChain()
if (chain?.id !== polygonAmoy.id) {
return (
<div>
<p>Please switch to Polygon Amoy</p>
<button onClick={() => switchChain({ chainId: polygonAmoy.id })}>
Switch Network
</button>
</div>
)
}
return <>{children}</>
}
Sign-In with Ethereum (SIWE)
Kuest implements SIWE for secure wallet-based authentication:
import { SIWESession } from '@reown/appkit-siwe'
const session = await SIWESession.signIn({
domain: window.location.host,
uri: window.location.origin,
statement: 'Sign in to Kuest Prediction Market',
})
console.log('Session:', session.address)
This generates a signed message that proves wallet ownership without exposing private keys.
Safe (Gnosis) wallet support
Kuest supports Safe multi-sig wallets through proxy contracts:
import { SAFE_PROXY_FACTORY_ADDRESS } from '@/lib/contracts'
export async function deploySafeProxy(ownerAddress: string) {
// Deploy Safe proxy for user
const proxyAddress = await deployProxy({
factory: SAFE_PROXY_FACTORY_ADDRESS,
owners: [ownerAddress],
threshold: 1,
})
return proxyAddress
}
Safe wallets require gas fees for proxy deployment. Ensure your wallet has POL for gas.
Trading authentication
After wallet connection, users must authorize trading:
Navigate to Settings → Trading
Access trading authentication settings.
Click 'Authorize Trading'
System generates CLOB API credentials.
Sign authorization message
Wallet signs a message to encrypt credentials.
Credentials stored securely
Encrypted credentials saved in database.
Implementation from src/lib/trading-auth/client.ts:
import { useSignMessage } from 'wagmi'
export function useTradingAuth() {
const { signMessageAsync } = useSignMessage()
const authorizeTrading = async () => {
// Generate signature for encryption
const signature = await signMessageAsync({
message: 'Authorize Kuest trading',
})
// Store encrypted credentials
await fetch('/api/auth/trading', {
method: 'POST',
body: JSON.stringify({ signature }),
})
}
return { authorizeTrading }
}
Two-factor authentication
For enhanced security, enable 2FA:
import { twoFactor } from 'better-auth/plugins'
const auth = betterAuth({
plugins: [
twoFactor({
issuer: 'Kuest',
totpOptions: {
period: 30,
digits: 6,
},
}),
],
})
Users scan a QR code to link their authenticator app.
Best practices
Never request private keys
Legitimate dApps never ask for private keys or seed phrases. All operations use wallet signatures.
Verify transaction details
Always display clear transaction details before requesting signature:
- Contract address
- Amount and token
- Gas estimate
Handle disconnections gracefully
Users may disconnect wallets at any time. Implement proper session cleanup:useEffect(() => {
if (!isConnected) {
// Clear trading session
clearTradingAuth()
}
}, [isConnected])
Support network switching
Auto-prompt users to switch to Polygon if on wrong network:if (chain?.id !== polygonAmoy.id) {
await switchChain({ chainId: polygonAmoy.id })
}
Troubleshooting
| Issue | Solution |
|---|
| ”Connect failed” | Check Reown Project ID is valid |
| ”Wrong network” | User needs to switch to Polygon |
| ”No wallets detected” | Install MetaMask or use WalletConnect |
| ”Transaction rejected” | User declined in wallet |
| ”Insufficient gas” | Add POL to wallet for gas fees |
Next steps
Polygon setup
Configure Polygon network
USDC operations
Deposit and withdraw USDC
Smart contracts
View contract addresses
Authentication
API authentication methods