Entros_docs
Reference

SDK reference

Public API surface of @entros/pulse-sdk.

@entros/pulse-sdk is the client SDK. It captures behavioral signals on-device, extracts statistical features, hashes the result, generates a zero-knowledge proof, and submits to Solana. This page lists every public export, grouped by purpose.

The current published version is 1.5.3. Install with npm install @entros/pulse-sdk. See the changelog for the upgrade path from earlier versions.

Top-level

ExportTypePurpose
PulseSDKclassHigh-level entry point. Construct once with config, call verify() per session.
PulseSessionclassLower-level session for fine-grained capture control.

Constants

ExportValuePurpose
PROGRAM_IDS{ entrosAnchor, entrosVerifier, entrosRegistry }Devnet program IDs
MIN_AUDIO_SAMPLES16000Minimum audio samples per capture
MIN_MOTION_SAMPLES10Minimum motion samples
MIN_TOUCH_SAMPLES10Minimum touch samples
MIN_CAPTURE_MS2000Minimum capture duration
MAX_CAPTURE_MS60000Maximum capture duration
DEFAULT_CAPTURE_MS7000Default capture duration
DEFAULT_THRESHOLD96Default Hamming distance threshold
DEFAULT_MIN_DISTANCE3Default minimum distance for replay defense
FINGERPRINT_BITS256Behavioral fingerprint width in bits
SPEAKER_FEATURE_COUNT44Number of voice features extracted

Capture and feature extraction

ExportSignaturePurpose
extractSpeakerFeatures(audio) => Promise<number[]>44 voice prosody features
extractSpeakerFeaturesDetailed(audio) => Promise<{ features, f0Contour }>Voice features plus pitch contour
extractMotionFeatures(samples) => number[]54 motion features from IMU samples
extractTouchFeatures(samples) => number[]36 touch features
extractMouseDynamics(samples) => number[]Pointer-based touch dynamics
extractAccelerationMagnitude(samples, frameCount) => number[]Frame-aligned acceleration magnitudes
fuseFeatures(audio, motion, touch) => number[]Concatenate the three feature streams
fuseRawFeatures(audio, motion, touch) => number[]Same, without pre-aggregation

Statistics utilities also exported: mean, variance, skewness, kurtosis, condense, entropy, autocorrelation.

Hashing

ExportSignaturePurpose
simhash(features) => TemporalFingerprint256-bit SimHash of the feature vector
hammingDistance(fp1, fp2) => numberBit-distance between two fingerprints
generateTBH(fingerprint) => Promise<TBH>Temporal Behavioral Hash with Poseidon commitment
generateSalt() => bigintCryptographic salt for the commitment
packBits(fingerprint) => PackedFingerprintPack the 256-bit fingerprint for circuit input
computeCommitment(fingerprint, salt) => bigintPoseidon commitment over BN254
bigintToBytes32(n) => Uint8ArrayBigInt to 32-byte big-endian array

Proof generation

ExportSignaturePurpose
prepareCircuitInput(tbhNew, tbhPrev, threshold) => CircuitInputFormat the inputs for the Hamming circuit
generateProof(input, wasmUrl, zkeyUrl) => Promise<ProofResult>Run Groth16 proving
serializeProof(proof, publicSignals) => SolanaProofSerialize to the verifier program's expected layout
toBigEndian32(decStr) => Uint8ArrayDecimal-string to big-endian bytes

Submission

ExportSignaturePurpose
submitViaWallet(proof, commitment, options) => Promise<SubmissionResult>Submit through a connected wallet
submitResetViaWallet(commitment, options) => Promise<SubmissionResult>Submit a recovery reset
submitViaRelayer(proof, commitment, options) => Promise<SubmissionResult>Submit through the executor's relayer. Used by the no-wallet capture preview on entros.io/verify; production integrations use submitViaWallet.

Challenge generation

ExportSignaturePurpose
generatePhrase(wordCount?) => stringRandom phrase prompt for voice capture
generatePhraseSequence(count) => string[]Multiple phrase prompts
randomLissajousParams() => LissajousParamsLissajous figure parameters for touch capture
generateLissajousPoints(params) => Point2D[]Render the curve
generateLissajousSequence(count) => Point2D[][]Multiple curves
fetchChallenge(executorUrl, walletAddress, apiKey?) => Promise<ChallengeResponse>Fetch a challenge from the executor

Audio encoding

ExportSignaturePurpose
encodeAudioAsBase64(samples) => stringBase64-encode audio for transport (relayer mode)

Attestation and on-chain reads

ExportSignaturePurpose
verifyEntrosAttestation(walletAddress, connection) => Promise<EntrosAttestation | null>Read a wallet's SAS attestation
attestAgentOperator(agentAsset: string, options: { wallet, connection, cluster? }) => Promise<{ success: boolean; signature?: string; error?: string }>Write the human-operator metadata for a registered agent
getAgentHumanOperator(agentAsset: string, connection?, cluster?) => Promise<AgentHumanOperator | null>Read the human-operator metadata. AgentHumanOperator fields: { anchorPda, trustScore, verifiedAt, wallet }
fetchIdentityState(wallet, connection) => Promise<IdentityState | null>Read the full Anchor PDA
storeVerificationData(data) => Promise<void>Persist verification state to local storage
loadVerificationData() => Promise<StoredVerificationData | null>Load persisted state

Configuration

PulseSDK is constructed with a PulseConfig:

type PulseConfig = {
  cluster: "devnet" | "mainnet-beta" | "localnet";
  rpcEndpoint?: string;
  relayerUrl?: string;
  relayerApiKey?: string;
  zkeyUrl?: string;
  wasmUrl?: string;
  threshold?: number;
  debug?: boolean;
  // Crypto-unavailable browsers (iOS Safari private mode, Brave shields,
  // Firefox Total Cookie Protection) hit this callback. Return true to allow
  // plaintext localStorage; false to keep storage in-memory only (data lost
  // on reload). Without the callback, the SDK defaults to in-memory only.
  onPrivacyFallback?: () => Promise<boolean>;
};

Verification result reasons

VerificationResult.reason (when success: false) is a narrow, client-side signal:

  • validation_unavailable — the executor's /validate-features endpoint was unreachable (network failure, timeout, abort). Treat as transient and offer a retry CTA.

The validator's server-side rejections do not surface a category code to the client by design — host code should not depend on a per-check breakdown. Build retry UX around the success boolean and an attempt counter, not a reason taxonomy. The reason field is absent on every server-side rejection, every on-chain submission failure, and every data-quality rejection.

Peer dependencies

The SDK declares the following as optional peers:

  • @coral-xyz/anchor ^0.32.1
  • @solana/wallet-adapter-base ^0.9.0
  • @solana/web3.js ^1.98.0
  • @solana/spl-token ^0.4.0

Install whichever you need for your integration path. For pure read flows (verifyEntrosAttestation, fetchIdentityState), only @solana/web3.js is required.

Where to look next

On this page