Skip to main content
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:
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
Get your Reown AppKit Project ID at dashboard.reown.com

Wallet connection flow

1

User initiates connection

User clicks “Connect Wallet” button in the UI.
2

AppKit modal opens

Reown AppKit displays available wallet options.
3

Wallet authentication

User approves connection in their wallet app.
4

Network verification

System verifies user is on Polygon (or switches network).
5

Session creation

App creates authenticated session for trading.

Implementation example

Connect button component

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:
src/lib/safe-proxy.ts
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:
1

Navigate to Settings → Trading

Access trading authentication settings.
2

Click 'Authorize Trading'

System generates CLOB API credentials.
3

Sign authorization message

Wallet signs a message to encrypt credentials.
4

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

Legitimate dApps never ask for private keys or seed phrases. All operations use wallet signatures.
Always display clear transaction details before requesting signature:
  • Contract address
  • Amount and token
  • Gas estimate
Users may disconnect wallets at any time. Implement proper session cleanup:
useEffect(() => {
  if (!isConnected) {
    // Clear trading session
    clearTradingAuth()
  }
}, [isConnected])
Auto-prompt users to switch to Polygon if on wrong network:
if (chain?.id !== polygonAmoy.id) {
  await switchChain({ chainId: polygonAmoy.id })
}

Troubleshooting

IssueSolution
”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

Build docs developers (and LLMs) love