Entros_docs
Integrate

Verification flow component

Drop in <EntrosVerify /> to take a user from unverified wallet to on-chain Anchor in one click. Five lines of JSX.

The verification flow ships as @entros/verify — a React component that opens a popup window to entros.io, runs the 12-second capture, signs the wallet transaction, and posts the verified payload back via the onVerified callback. Your app never touches the wallet adapter or the SDK directly until the result arrives.

This is the Tier 1 path. It's the right choice for ~90% of integrations. Tier 2 (custom UX with the Pulse SDK directly) is documented at Reference → SDK.

Install

npm install @entros/verify

The package declares react ^19 and react-dom ^19 as peer dependencies. No Solana adapter, no SDK, no web3.js install — those live behind the popup boundary on entros.io.

Five-line usage

import { EntrosVerify } from "@entros/verify";

<EntrosVerify
  integratorKey="your-integrator-key"
  onVerified={(result) => grantAccess(result.walletPubkey)}
/>

What this does on click:

  1. Opens a popup window to https://entros.io/embed/verify-popup with your integrator key and origin
  2. The popup hosts wallet connect (Phantom, Solflare, Backpack)
  3. The user completes the 12-second voice + motion + touch capture
  4. The Pulse SDK extracts features, generates a Groth16 proof, submits to Solana
  5. On success, the popup posts back to your page; onVerified fires with the verified payload

The verified payload

interface EntrosVerifyResult {
  walletPubkey: string;       // Base58 Solana wallet address
  attestationPda: string;     // SAS attestation PDA — readable by any Solana program
  txSig: string;              // Confirmed transaction signature
  trustScore: number;         // On-chain Trust Score after this verification
  cluster: "devnet" | "mainnet-beta";
}

Use walletPubkey to identify the user. Use trustScore if you want a higher gate than "verified once" (e.g., require 100+ for airdrop eligibility). Use attestationPda and txSig for audit trails.

Optional props

<EntrosVerify
  integratorKey="my-app"
  cluster="devnet"                            // defaults to "devnet"
  minTrustScore={100}                          // optional gate enforced inside the popup
  onVerified={(result) => grantAccess(result)}
  onError={(err) => console.warn(err.reason)}  // wallet_rejected | validation_failed | network_error | user_canceled | origin_invalid | popup_blocked | timeout | unknown
  onProgress={(p) => setStatus(p.status)}      // wallet_connecting → capturing → proving → submitting → attesting
  popupWidth={520}                             // defaults to 480
  popupHeight={760}                            // defaults to 720
  timeoutMs={5 * 60 * 1000}                    // defaults to 5 minutes
  popupBlockedFallback                         // defaults to true — renders a manual retry button when the browser blocks the popup
>
  Verify with Entros
</EntrosVerify>

children overrides the button label. The component renders a single <button> element with whatever children you pass; style it with className or style.

Error handling

Every failure routes to onError with an opaque category. The popup shows a brief failure surface (or, for stale-baseline cases, a recovery surface linking to the reset path) before closing itself.

ReasonMeaningRecovery
wallet_rejectedUser canceled the wallet signature, or the wallet had insufficient SOLUser retries from your button
validation_failedValidator rejected the capture (variance, entropy, phrase mismatch, sybil match, or stale baseline)User retries — for stale-baseline cases the popup itself surfaces the reset option
network_errorValidator unreachable, blockhash expired, RPC errorTransient — user retries
user_canceledUser closed the popup window before completingUser retries
origin_invalidPopup loaded from an origin not registered for this integratorKeyRegister the origin (see Integrator key registration below)
popup_blockedBrowser blocked window.openComponent renders an inline retry button (set popupBlockedFallback={false} to disable)
timeoutPopup stayed open longer than timeoutMsUser retries
unknownAnything elseLog and retry

Integrator key registration

Each integrator key is registered with the popup-host's allowlist along with the production origins it's allowed to be opened from. To register, open an issue at github.com/entros-protocol/entros-verify or reach out via Discord. Keys are added to a JSON allowlist on the entros.io deployment within a deploy cycle.

For local development, the popup-host accepts any localhost origin without registration so you can iterate before formal registration.

Custom UX

If you need to own the verification UX — capture inline, branded prompts, mobile-native — install @entros/pulse-sdk directly. See Reference → SDK for the lower-level primitives (PulseSDK, PulseSession, extractSpeakerFeatures, simhash, generateProof, submitViaWallet).

The Pulse SDK is what @entros/verify uses internally on the popup-host side, so the two paths produce identical on-chain state.

On this page