PollarPollar
Guides

Deferred Flow Guide

Deferred mode creates user wallets on-chain without funding them immediately. The XLM reserve is only charged when your backend calls POST /activate — typically after a business event like KYC approval or a first deposit.

This guide walks through the full implementation end-to-end.


Prerequisites

  • Funding mode set to Deferred in Dashboard → Configuration → Funding Mode
  • A secret key from Dashboard → Configuration → API Keys
  • That's it — no additional dashboard configuration required

How it works


Step 1 — Detect pending wallets in the frontend

After login, check the wallet status. If pending, show your KYC or onboarding flow instead of the wallet UI.

'use client';
import { usePollar } from '@pollar/react';

export function WalletGate() {
  const { wallet, loading } = usePollar();

  if (loading) return <p>Loading...</p>;

  if (!wallet) return <LoginButton />;

  if (wallet.status === 'pending') {
    return <KycFlow walletId={wallet.id} />;
  }

  return <WalletDashboard />;
}

Step 2 — Trigger activation from your backend

When the business event occurs (KYC approved, first deposit confirmed, etc.), your backend calls POST /activate using the secret key.

// Your backend — e.g. Next.js API route, Express handler, webhook receiver
async function activateWallet(walletId: string) {
  const response = await fetch('https://api.pollar.xyz/wallets/activate', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.POLLAR_SECRET_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ walletId }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Activation failed: ${error.error.code}`);
  }

  return response.json();
  // { walletId, address, status: 'active', activatedAt }
}

Never call POST /activate from the client. It requires your secret key — exposing it client-side compromises your entire app.


Step 3 — Handle the response

CodeMeaningAction
200 OKWallet activated successfullyProceed — wallet is funded on-chain
400 Bad RequestMissing or malformed walletIdCheck the request payload
402 Payment RequiredFunding wallet has insufficient XLMTop up via Dashboard → Configuration → App Wallets
404 Not FoundwalletId does not existVerify the wallet ID
409 ConflictWallet already activeSafe to ignore — treat as success
503 Service UnavailableStellar network issuePollar retries automatically

Step 4 — Notify the frontend

After activation, notify your frontend so the UI updates. The simplest approach is polling wallet.status. For real-time updates, use a websocket or server-sent event from your backend.

'use client';
import { usePollar } from '@pollar/react';
import { useEffect } from 'react';

export function KycFlow({ walletId }: { walletId: string }) {
  const { wallet, refetchWallet } = usePollar();

  // Poll every 2 seconds until wallet is active
  useEffect(() => {
    if (wallet?.status === 'active') return;
    const interval = setInterval(refetchWallet, 2000);
    return () => clearInterval(interval);
  }, [wallet?.status]);

  if (wallet?.status === 'active') {
    return <p>✓ Wallet activated</p>;
  }

  return <p>Complete KYC to activate your wallet...</p>;
}

Full Next.js example

The template-nextjs demo includes a working implementation:

  • app/api/activate/route.ts — the API route that calls POST /activate
  • app/components/KycGate.tsx — the frontend component that triggers it

Testing on testnet

  1. Set funding mode to Deferred in the Dashboard
  2. Log in — the wallet is created with status: 'pending'
  3. Call your activate endpoint manually (e.g. with curl or Postman)
  4. Verify the wallet moves to status: 'active'
  5. Verify the G-address on Stellar Expert testnet
curl -X POST https://api.pollar.xyz/wallets/activate \
  -H "Authorization: Bearer sec_testnet_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "walletId": "wal_abc123" }'

On this page

Was this helpful?