Skip to main content
The authenticate function will return the user’s wallet address and a signed message that verifies wallet ownership. This should be the primary authentication method for your Mini App. Uses Sign In With Ethereum (SIWE) to sign a message that contains a nonce that should be generated in your backend.

Usage

import { authenticate, TransactionResult } from '@lemoncash/mini-app-sdk';

export const MiniApp = () => {
  const [wallet, setWallet] = useState<string | undefined>(undefined);

  const handleAuthentication = async () => {
    const result = await authenticate();
    
    if (result.result === TransactionResult.SUCCESS) {
      setWallet(result.data.wallet);
    }
  };

  useEffect(() => {
    handleAuthentication();
  }, []);
};

Parameters

type AuthenticateData = {
  nonce?: string;
  chainId?: ChainId;
}
nonce
string
If present, it must be at least 8 alphanumeric characters in length. A unique nonce for the authentication request. This should be generated in your backend and be different for each authentication attempt.
await authenticate({
  nonce: 'l3m0nc45h',
});
chainId
ChainId
If your Mini App supports multiple chains, you can provide the chain id to use for the authentication request.
import { ChainId } from '@lemoncash/mini-app-sdk';

await authenticate({
  chainId: ChainId.POLYGON_AMOY,
});

Returns

type AuthenticateResponse = {
  result: TransactionResult.SUCCESS;
  data: {
    wallet: string;
    signature: string;
    message: string;
  };
} | {
  result: TransactionResult.FAILED;
  error: {
    message: string;
    code: string;
  };
} | {
  result: TransactionResult.CANCELLED;
};
result
TransactionResult
The result of the authentication attempt.
  • SUCCESS: The authentication was successful.
  • FAILED: The authentication failed.
  • CANCELLED: The authentication was cancelled by the user.
data
object
Contains the wallet address, signature and message. Only present when the result is SUCCESS.
  • wallet: The wallet address of the authenticated user.
  • signature: The cryptographic signature proving the user’s authentication.
  • message: The message that was signed by the user’s wallet.
error
object
Contains the error details when the authentication fails. Only present when the result is FAILED.
  • message: A human-readable error message describing what went wrong.
  • code: A machine-readable error code for programmatic error handling.

Complete Authentication Flow

Backend endpoints The backend is responsible for generating a nonce and verifying the signature.
import crypto from 'crypto';

// Generate a cryptographically secure nonce
async function generateNonce(): Promise<string> {
  // Generate 32 random bytes and convert to hex
  const nonce = crypto.randomBytes(32).toString('hex');
  
  // TODO: Store the nonce in your database with:
  // - timestamp for expiration
  // - used flag to prevent replay attacks
  // - user identifier
  
  return nonce;
}

app.post('/api/auth/nonce', async (req, res) => {
    const nonce = await generateNonce();
    res.json({ nonce });
});
Frontend React component:
import React, { useState, useEffect } from 'react';
import { authenticate, ChainId, TransactionResult } from '@lemoncash/mini-app-sdk';
import { getNonceFromBackend, verifySignatureOnBackend } from './api';

export const MiniApp: React.FC = () => {
  const [wallet, setWallet] = useState<string | undefined>(undefined);

  const handleAuthenticate = async () => {    
    // 1. Get a unique nonce from your backend
    const nonce = await getNonceFromBackend();
    
    // 2. Request the signature using the nonce
    const result = await authenticate({ 
      nonce, 
      chainId: ChainId.POLYGON_AMOY 
    });
    
    if (result.result === TransactionResult.FAILED) {
      throw new Error(`Authentication failed: ${result.error.message} (${result.error.code})`);
    }
    
    if (result.result === TransactionResult.CANCELLED) {
      throw new Error('Authentication was cancelled by the user');
    }
    
    const { wallet, signature, message } = result.data;
    
    // 3. Verify the signature on your backend
    const verificationResult = await verifySignatureOnBackend({
      wallet,
      signature,
      message,
      nonce,
    });
    
    if (verificationResult.verified) {
      setWallet(wallet);
    }
  };

  // Trigger authentication on component mount
  useEffect(() => {
    handleAuthenticate();
  }, []);

  return (
    <div>
      <h2>Wallet</h2>
      <p>
        Connected: {wallet ? '✅ Connected' : '❌ Not connected'}
      </p>
      
      {wallet && (
        <p>
          {wallet}
        </p>
      )}
    </div>
  );
};

ERC-6492 Support

The smart contract wallet is deployed on the first user’s transaction. The authenticate method supports ERC-6492 for contract wallets that are not yet deployed. This means users can authenticate even before their wallet contract is deployed.