@iam-protocol/pulse-sdk 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +17 -5
- package/dist/index.d.ts +17 -5
- package/dist/index.js +71 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +68 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/config.ts +2 -1
- package/src/extraction/kinematic.ts +28 -5
- package/src/extraction/mfcc.ts +11 -4
- package/src/extraction/statistics.ts +46 -0
- package/src/index.ts +2 -2
- package/src/proof/prover.ts +4 -2
- package/src/proof/types.ts +1 -0
- package/src/pulse.ts +2 -3
- package/src/sensor/audio.ts +1 -9
- package/src/sensor/types.ts +0 -2
- package/test/integration.test.ts +3 -2
- package/test/serializer.test.ts +1 -0
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
declare const FINGERPRINT_BITS = 256;
|
|
2
2
|
declare const DEFAULT_THRESHOLD = 30;
|
|
3
|
+
declare const DEFAULT_MIN_DISTANCE = 3;
|
|
3
4
|
declare const MIN_CAPTURE_MS = 2000;
|
|
4
5
|
declare const MAX_CAPTURE_MS = 60000;
|
|
5
6
|
declare const DEFAULT_CAPTURE_MS = 7000;
|
|
@@ -50,8 +51,6 @@ interface CaptureOptions {
|
|
|
50
51
|
minDurationMs?: number;
|
|
51
52
|
/** Maximum capture duration in ms. Auto-stops if signal hasn't fired. Default: 60000 */
|
|
52
53
|
maxDurationMs?: number;
|
|
53
|
-
/** Called with RMS audio level (0-1) on each buffer during audio capture (~4x per second). */
|
|
54
|
-
onAudioLevel?: (rms: number) => void;
|
|
55
54
|
}
|
|
56
55
|
/** Stage of a capture session */
|
|
57
56
|
type CaptureStage = "audio" | "motion" | "touch";
|
|
@@ -120,7 +119,7 @@ declare class PulseSession {
|
|
|
120
119
|
private motionData;
|
|
121
120
|
private touchData;
|
|
122
121
|
constructor(config: ResolvedConfig, touchElement?: HTMLElement);
|
|
123
|
-
startAudio(
|
|
122
|
+
startAudio(): Promise<void>;
|
|
124
123
|
stopAudio(): Promise<AudioCapture | null>;
|
|
125
124
|
skipAudio(): void;
|
|
126
125
|
startMotion(): Promise<void>;
|
|
@@ -224,6 +223,18 @@ declare function variance(values: number[], mu?: number): number;
|
|
|
224
223
|
declare function skewness(values: number[]): number;
|
|
225
224
|
declare function kurtosis(values: number[]): number;
|
|
226
225
|
declare function condense(values: number[]): StatsSummary;
|
|
226
|
+
/**
|
|
227
|
+
* Shannon entropy over histogram bins. Measures information density.
|
|
228
|
+
* Real human data has moderate entropy (varied but structured).
|
|
229
|
+
* Synthetic data is either too uniform (high entropy) or too structured (low entropy).
|
|
230
|
+
*/
|
|
231
|
+
declare function entropy(values: number[], bins?: number): number;
|
|
232
|
+
/**
|
|
233
|
+
* Autocorrelation at a given lag. Detects periodic synthetic patterns.
|
|
234
|
+
* Real human data has low autocorrelation at most lags (chaotic/noisy).
|
|
235
|
+
* Synthetic data often has high autocorrelation (periodic/smooth).
|
|
236
|
+
*/
|
|
237
|
+
declare function autocorrelation(values: number[], lag?: number): number;
|
|
227
238
|
declare function fuseFeatures(audio: number[], motion: number[], touch: number[]): number[];
|
|
228
239
|
|
|
229
240
|
/** Serialized proof ready for on-chain submission */
|
|
@@ -248,6 +259,7 @@ interface CircuitInput {
|
|
|
248
259
|
commitment_new: string;
|
|
249
260
|
commitment_prev: string;
|
|
250
261
|
threshold: string;
|
|
262
|
+
min_distance: string;
|
|
251
263
|
}
|
|
252
264
|
/** Proof generation result */
|
|
253
265
|
interface ProofResult {
|
|
@@ -271,7 +283,7 @@ declare function serializeProof(proof: RawProof, publicSignals: string[]): Solan
|
|
|
271
283
|
/**
|
|
272
284
|
* Prepare circuit input from current and previous TBH data.
|
|
273
285
|
*/
|
|
274
|
-
declare function prepareCircuitInput(current: TBH, previous: TBH, threshold?: number): CircuitInput;
|
|
286
|
+
declare function prepareCircuitInput(current: TBH, previous: TBH, threshold?: number, minDistance?: number): CircuitInput;
|
|
275
287
|
/**
|
|
276
288
|
* Generate a Groth16 proof for the Hamming distance circuit.
|
|
277
289
|
*
|
|
@@ -375,4 +387,4 @@ declare function randomLissajousParams(): LissajousParams;
|
|
|
375
387
|
*/
|
|
376
388
|
declare function generateLissajousPoints(params: LissajousParams): Point2D[];
|
|
377
389
|
|
|
378
|
-
export { type AudioCapture, type CaptureOptions, type CaptureStage, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_THRESHOLD, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_CAPTURE_MS, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, type SensorData, type SolanaProof, type StageState, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, type TemporalFingerprint, type TouchSample, type VerificationResult, bigintToBytes32, computeCommitment, condense, fetchIdentityState, fuseFeatures, generateLissajousPoints, generatePhrase, generateProof, generateSalt, generateSolanaProof, generateTBH, hammingDistance, kurtosis, loadVerificationData, mean, packBits, prepareCircuitInput, randomLissajousParams, serializeProof, simhash, skewness, storeVerificationData, submitViaRelayer, submitViaWallet, toBigEndian32, variance };
|
|
390
|
+
export { type AudioCapture, type CaptureOptions, type CaptureStage, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_MIN_DISTANCE, DEFAULT_THRESHOLD, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_CAPTURE_MS, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, type SensorData, type SolanaProof, type StageState, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, type TemporalFingerprint, type TouchSample, type VerificationResult, autocorrelation, bigintToBytes32, computeCommitment, condense, entropy, fetchIdentityState, fuseFeatures, generateLissajousPoints, generatePhrase, generateProof, generateSalt, generateSolanaProof, generateTBH, hammingDistance, kurtosis, loadVerificationData, mean, packBits, prepareCircuitInput, randomLissajousParams, serializeProof, simhash, skewness, storeVerificationData, submitViaRelayer, submitViaWallet, toBigEndian32, variance };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
declare const FINGERPRINT_BITS = 256;
|
|
2
2
|
declare const DEFAULT_THRESHOLD = 30;
|
|
3
|
+
declare const DEFAULT_MIN_DISTANCE = 3;
|
|
3
4
|
declare const MIN_CAPTURE_MS = 2000;
|
|
4
5
|
declare const MAX_CAPTURE_MS = 60000;
|
|
5
6
|
declare const DEFAULT_CAPTURE_MS = 7000;
|
|
@@ -50,8 +51,6 @@ interface CaptureOptions {
|
|
|
50
51
|
minDurationMs?: number;
|
|
51
52
|
/** Maximum capture duration in ms. Auto-stops if signal hasn't fired. Default: 60000 */
|
|
52
53
|
maxDurationMs?: number;
|
|
53
|
-
/** Called with RMS audio level (0-1) on each buffer during audio capture (~4x per second). */
|
|
54
|
-
onAudioLevel?: (rms: number) => void;
|
|
55
54
|
}
|
|
56
55
|
/** Stage of a capture session */
|
|
57
56
|
type CaptureStage = "audio" | "motion" | "touch";
|
|
@@ -120,7 +119,7 @@ declare class PulseSession {
|
|
|
120
119
|
private motionData;
|
|
121
120
|
private touchData;
|
|
122
121
|
constructor(config: ResolvedConfig, touchElement?: HTMLElement);
|
|
123
|
-
startAudio(
|
|
122
|
+
startAudio(): Promise<void>;
|
|
124
123
|
stopAudio(): Promise<AudioCapture | null>;
|
|
125
124
|
skipAudio(): void;
|
|
126
125
|
startMotion(): Promise<void>;
|
|
@@ -224,6 +223,18 @@ declare function variance(values: number[], mu?: number): number;
|
|
|
224
223
|
declare function skewness(values: number[]): number;
|
|
225
224
|
declare function kurtosis(values: number[]): number;
|
|
226
225
|
declare function condense(values: number[]): StatsSummary;
|
|
226
|
+
/**
|
|
227
|
+
* Shannon entropy over histogram bins. Measures information density.
|
|
228
|
+
* Real human data has moderate entropy (varied but structured).
|
|
229
|
+
* Synthetic data is either too uniform (high entropy) or too structured (low entropy).
|
|
230
|
+
*/
|
|
231
|
+
declare function entropy(values: number[], bins?: number): number;
|
|
232
|
+
/**
|
|
233
|
+
* Autocorrelation at a given lag. Detects periodic synthetic patterns.
|
|
234
|
+
* Real human data has low autocorrelation at most lags (chaotic/noisy).
|
|
235
|
+
* Synthetic data often has high autocorrelation (periodic/smooth).
|
|
236
|
+
*/
|
|
237
|
+
declare function autocorrelation(values: number[], lag?: number): number;
|
|
227
238
|
declare function fuseFeatures(audio: number[], motion: number[], touch: number[]): number[];
|
|
228
239
|
|
|
229
240
|
/** Serialized proof ready for on-chain submission */
|
|
@@ -248,6 +259,7 @@ interface CircuitInput {
|
|
|
248
259
|
commitment_new: string;
|
|
249
260
|
commitment_prev: string;
|
|
250
261
|
threshold: string;
|
|
262
|
+
min_distance: string;
|
|
251
263
|
}
|
|
252
264
|
/** Proof generation result */
|
|
253
265
|
interface ProofResult {
|
|
@@ -271,7 +283,7 @@ declare function serializeProof(proof: RawProof, publicSignals: string[]): Solan
|
|
|
271
283
|
/**
|
|
272
284
|
* Prepare circuit input from current and previous TBH data.
|
|
273
285
|
*/
|
|
274
|
-
declare function prepareCircuitInput(current: TBH, previous: TBH, threshold?: number): CircuitInput;
|
|
286
|
+
declare function prepareCircuitInput(current: TBH, previous: TBH, threshold?: number, minDistance?: number): CircuitInput;
|
|
275
287
|
/**
|
|
276
288
|
* Generate a Groth16 proof for the Hamming distance circuit.
|
|
277
289
|
*
|
|
@@ -375,4 +387,4 @@ declare function randomLissajousParams(): LissajousParams;
|
|
|
375
387
|
*/
|
|
376
388
|
declare function generateLissajousPoints(params: LissajousParams): Point2D[];
|
|
377
389
|
|
|
378
|
-
export { type AudioCapture, type CaptureOptions, type CaptureStage, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_THRESHOLD, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_CAPTURE_MS, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, type SensorData, type SolanaProof, type StageState, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, type TemporalFingerprint, type TouchSample, type VerificationResult, bigintToBytes32, computeCommitment, condense, fetchIdentityState, fuseFeatures, generateLissajousPoints, generatePhrase, generateProof, generateSalt, generateSolanaProof, generateTBH, hammingDistance, kurtosis, loadVerificationData, mean, packBits, prepareCircuitInput, randomLissajousParams, serializeProof, simhash, skewness, storeVerificationData, submitViaRelayer, submitViaWallet, toBigEndian32, variance };
|
|
390
|
+
export { type AudioCapture, type CaptureOptions, type CaptureStage, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_MIN_DISTANCE, DEFAULT_THRESHOLD, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_CAPTURE_MS, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, type SensorData, type SolanaProof, type StageState, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, type TemporalFingerprint, type TouchSample, type VerificationResult, autocorrelation, bigintToBytes32, computeCommitment, condense, entropy, fetchIdentityState, fuseFeatures, generateLissajousPoints, generatePhrase, generateProof, generateSalt, generateSolanaProof, generateTBH, hammingDistance, kurtosis, loadVerificationData, mean, packBits, prepareCircuitInput, randomLissajousParams, serializeProof, simhash, skewness, storeVerificationData, submitViaRelayer, submitViaWallet, toBigEndian32, variance };
|
package/dist/index.js
CHANGED
|
@@ -12978,6 +12978,7 @@ var init_esm4 = __esm({
|
|
|
12978
12978
|
var index_exports = {};
|
|
12979
12979
|
__export(index_exports, {
|
|
12980
12980
|
DEFAULT_CAPTURE_MS: () => DEFAULT_CAPTURE_MS,
|
|
12981
|
+
DEFAULT_MIN_DISTANCE: () => DEFAULT_MIN_DISTANCE,
|
|
12981
12982
|
DEFAULT_THRESHOLD: () => DEFAULT_THRESHOLD,
|
|
12982
12983
|
FINGERPRINT_BITS: () => FINGERPRINT_BITS,
|
|
12983
12984
|
MAX_CAPTURE_MS: () => MAX_CAPTURE_MS,
|
|
@@ -12985,9 +12986,11 @@ __export(index_exports, {
|
|
|
12985
12986
|
PROGRAM_IDS: () => PROGRAM_IDS,
|
|
12986
12987
|
PulseSDK: () => PulseSDK,
|
|
12987
12988
|
PulseSession: () => PulseSession,
|
|
12989
|
+
autocorrelation: () => autocorrelation,
|
|
12988
12990
|
bigintToBytes32: () => bigintToBytes32,
|
|
12989
12991
|
computeCommitment: () => computeCommitment,
|
|
12990
12992
|
condense: () => condense,
|
|
12993
|
+
entropy: () => entropy,
|
|
12991
12994
|
fetchIdentityState: () => fetchIdentityState,
|
|
12992
12995
|
fuseFeatures: () => fuseFeatures,
|
|
12993
12996
|
generateLissajousPoints: () => generateLissajousPoints,
|
|
@@ -13023,6 +13026,7 @@ var BN254_SCALAR_FIELD = BigInt(
|
|
|
13023
13026
|
);
|
|
13024
13027
|
var FINGERPRINT_BITS = 256;
|
|
13025
13028
|
var DEFAULT_THRESHOLD = 30;
|
|
13029
|
+
var DEFAULT_MIN_DISTANCE = 3;
|
|
13026
13030
|
var PROOF_A_SIZE = 64;
|
|
13027
13031
|
var PROOF_B_SIZE = 128;
|
|
13028
13032
|
var PROOF_C_SIZE = 64;
|
|
@@ -13043,8 +13047,7 @@ async function captureAudio(options = {}) {
|
|
|
13043
13047
|
const {
|
|
13044
13048
|
signal,
|
|
13045
13049
|
minDurationMs = MIN_CAPTURE_MS,
|
|
13046
|
-
maxDurationMs = MAX_CAPTURE_MS
|
|
13047
|
-
onAudioLevel
|
|
13050
|
+
maxDurationMs = MAX_CAPTURE_MS
|
|
13048
13051
|
} = options;
|
|
13049
13052
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
13050
13053
|
audio: {
|
|
@@ -13064,13 +13067,7 @@ async function captureAudio(options = {}) {
|
|
|
13064
13067
|
const bufferSize = 4096;
|
|
13065
13068
|
const processor = ctx.createScriptProcessor(bufferSize, 1, 1);
|
|
13066
13069
|
processor.onaudioprocess = (e2) => {
|
|
13067
|
-
|
|
13068
|
-
chunks.push(new Float32Array(data));
|
|
13069
|
-
if (onAudioLevel) {
|
|
13070
|
-
let sum = 0;
|
|
13071
|
-
for (let i = 0; i < data.length; i++) sum += data[i] * data[i];
|
|
13072
|
-
onAudioLevel(Math.sqrt(sum / data.length));
|
|
13073
|
-
}
|
|
13070
|
+
chunks.push(new Float32Array(e2.inputBuffer.getChannelData(0)));
|
|
13074
13071
|
};
|
|
13075
13072
|
source.connect(processor);
|
|
13076
13073
|
processor.connect(ctx.destination);
|
|
@@ -13269,6 +13266,37 @@ function condense(values) {
|
|
|
13269
13266
|
kurtosis: kurtosis(values)
|
|
13270
13267
|
};
|
|
13271
13268
|
}
|
|
13269
|
+
function entropy(values, bins = 16) {
|
|
13270
|
+
if (values.length < 2) return 0;
|
|
13271
|
+
const min = Math.min(...values);
|
|
13272
|
+
const max = Math.max(...values);
|
|
13273
|
+
if (min === max) return 0;
|
|
13274
|
+
const counts = new Array(bins).fill(0);
|
|
13275
|
+
const range = max - min;
|
|
13276
|
+
for (const v of values) {
|
|
13277
|
+
const idx = Math.min(Math.floor((v - min) / range * bins), bins - 1);
|
|
13278
|
+
counts[idx]++;
|
|
13279
|
+
}
|
|
13280
|
+
let h = 0;
|
|
13281
|
+
for (const c of counts) {
|
|
13282
|
+
if (c > 0) {
|
|
13283
|
+
const p = c / values.length;
|
|
13284
|
+
h -= p * Math.log2(p);
|
|
13285
|
+
}
|
|
13286
|
+
}
|
|
13287
|
+
return h;
|
|
13288
|
+
}
|
|
13289
|
+
function autocorrelation(values, lag = 1) {
|
|
13290
|
+
if (values.length <= lag) return 0;
|
|
13291
|
+
const m = mean(values);
|
|
13292
|
+
const v = variance(values, m);
|
|
13293
|
+
if (v === 0) return 0;
|
|
13294
|
+
let sum = 0;
|
|
13295
|
+
for (let i = 0; i < values.length - lag; i++) {
|
|
13296
|
+
sum += (values[i] - m) * (values[i + lag] - m);
|
|
13297
|
+
}
|
|
13298
|
+
return sum / ((values.length - lag) * v);
|
|
13299
|
+
}
|
|
13272
13300
|
function fuseFeatures(audio, motion, touch) {
|
|
13273
13301
|
return [...audio, ...motion, ...touch];
|
|
13274
13302
|
}
|
|
@@ -13283,10 +13311,10 @@ function extractMFCC(audio) {
|
|
|
13283
13311
|
try {
|
|
13284
13312
|
Meyda = require("meyda");
|
|
13285
13313
|
} catch {
|
|
13286
|
-
return new Array(NUM_MFCC * 3 * 4).fill(0);
|
|
13314
|
+
return new Array(NUM_MFCC * 3 * 4 + NUM_MFCC).fill(0);
|
|
13287
13315
|
}
|
|
13288
13316
|
const numFrames = Math.floor((samples.length - FRAME_SIZE) / HOP_SIZE) + 1;
|
|
13289
|
-
if (numFrames < 3) return new Array(NUM_MFCC * 3 * 4).fill(0);
|
|
13317
|
+
if (numFrames < 3) return new Array(NUM_MFCC * 3 * 4 + NUM_MFCC).fill(0);
|
|
13290
13318
|
const mfccFrames = [];
|
|
13291
13319
|
for (let i = 0; i < numFrames; i++) {
|
|
13292
13320
|
const start = i * HOP_SIZE;
|
|
@@ -13321,6 +13349,10 @@ function extractMFCC(audio) {
|
|
|
13321
13349
|
const stats = condense(dd);
|
|
13322
13350
|
features.push(stats.mean, stats.variance, stats.skewness, stats.kurtosis);
|
|
13323
13351
|
}
|
|
13352
|
+
for (let c = 0; c < NUM_MFCC; c++) {
|
|
13353
|
+
const raw = mfccFrames.map((f) => f[c] ?? 0);
|
|
13354
|
+
features.push(entropy(raw));
|
|
13355
|
+
}
|
|
13324
13356
|
return features;
|
|
13325
13357
|
}
|
|
13326
13358
|
function computeDeltas(frames) {
|
|
@@ -13335,7 +13367,7 @@ function computeDeltas(frames) {
|
|
|
13335
13367
|
|
|
13336
13368
|
// src/extraction/kinematic.ts
|
|
13337
13369
|
function extractMotionFeatures(samples) {
|
|
13338
|
-
if (samples.length < 5) return new Array(
|
|
13370
|
+
if (samples.length < 5) return new Array(54).fill(0);
|
|
13339
13371
|
const axes = {
|
|
13340
13372
|
ax: samples.map((s) => s.ax),
|
|
13341
13373
|
ay: samples.map((s) => s.ay),
|
|
@@ -13361,10 +13393,19 @@ function extractMotionFeatures(samples) {
|
|
|
13361
13393
|
jounceStats.kurtosis
|
|
13362
13394
|
);
|
|
13363
13395
|
}
|
|
13396
|
+
for (const values of Object.values(axes)) {
|
|
13397
|
+
const jerk = derivative(values);
|
|
13398
|
+
const windowSize = Math.max(5, Math.floor(jerk.length / 4));
|
|
13399
|
+
const windowVariances = [];
|
|
13400
|
+
for (let i = 0; i <= jerk.length - windowSize; i += windowSize) {
|
|
13401
|
+
windowVariances.push(variance(jerk.slice(i, i + windowSize)));
|
|
13402
|
+
}
|
|
13403
|
+
features.push(windowVariances.length >= 2 ? variance(windowVariances) : 0);
|
|
13404
|
+
}
|
|
13364
13405
|
return features;
|
|
13365
13406
|
}
|
|
13366
13407
|
function extractTouchFeatures(samples) {
|
|
13367
|
-
if (samples.length < 5) return new Array(
|
|
13408
|
+
if (samples.length < 5) return new Array(36).fill(0);
|
|
13368
13409
|
const x = samples.map((s) => s.x);
|
|
13369
13410
|
const y = samples.map((s) => s.y);
|
|
13370
13411
|
const pressure = samples.map((s) => s.pressure);
|
|
@@ -13384,6 +13425,14 @@ function extractTouchFeatures(samples) {
|
|
|
13384
13425
|
const jerkY = derivative(accY);
|
|
13385
13426
|
features.push(...Object.values(condense(jerkX)));
|
|
13386
13427
|
features.push(...Object.values(condense(jerkY)));
|
|
13428
|
+
for (const values of [vx, vy, pressure, area]) {
|
|
13429
|
+
const windowSize = Math.max(5, Math.floor(values.length / 4));
|
|
13430
|
+
const windowVariances = [];
|
|
13431
|
+
for (let i = 0; i <= values.length - windowSize; i += windowSize) {
|
|
13432
|
+
windowVariances.push(variance(values.slice(i, i + windowSize)));
|
|
13433
|
+
}
|
|
13434
|
+
features.push(windowVariances.length >= 2 ? variance(windowVariances) : 0);
|
|
13435
|
+
}
|
|
13387
13436
|
return features;
|
|
13388
13437
|
}
|
|
13389
13438
|
function derivative(values) {
|
|
@@ -13565,7 +13614,7 @@ async function getSnarkjs() {
|
|
|
13565
13614
|
}
|
|
13566
13615
|
return snarkjsModule;
|
|
13567
13616
|
}
|
|
13568
|
-
function prepareCircuitInput(current, previous, threshold = DEFAULT_THRESHOLD) {
|
|
13617
|
+
function prepareCircuitInput(current, previous, threshold = DEFAULT_THRESHOLD, minDistance = DEFAULT_MIN_DISTANCE) {
|
|
13569
13618
|
return {
|
|
13570
13619
|
ft_new: current.fingerprint,
|
|
13571
13620
|
ft_prev: previous.fingerprint,
|
|
@@ -13573,7 +13622,8 @@ function prepareCircuitInput(current, previous, threshold = DEFAULT_THRESHOLD) {
|
|
|
13573
13622
|
salt_prev: previous.salt.toString(),
|
|
13574
13623
|
commitment_new: current.commitment.toString(),
|
|
13575
13624
|
commitment_prev: previous.commitment.toString(),
|
|
13576
|
-
threshold: threshold.toString()
|
|
13625
|
+
threshold: threshold.toString(),
|
|
13626
|
+
min_distance: minDistance.toString()
|
|
13577
13627
|
};
|
|
13578
13628
|
}
|
|
13579
13629
|
async function generateProof(input, wasmPath, zkeyPath) {
|
|
@@ -13791,7 +13841,7 @@ var inMemoryStore = null;
|
|
|
13791
13841
|
|
|
13792
13842
|
// src/pulse.ts
|
|
13793
13843
|
function extractFeatures(data) {
|
|
13794
|
-
const audioFeatures = data.audio ? extractMFCC(data.audio) : new Array(
|
|
13844
|
+
const audioFeatures = data.audio ? extractMFCC(data.audio) : new Array(169).fill(0);
|
|
13795
13845
|
const motionFeatures = extractMotionFeatures(data.motion);
|
|
13796
13846
|
const touchFeatures = extractTouchFeatures(data.touch);
|
|
13797
13847
|
return fuseFeatures(audioFeatures, motionFeatures, touchFeatures);
|
|
@@ -13887,14 +13937,13 @@ var PulseSession = class {
|
|
|
13887
13937
|
this.touchElement = touchElement;
|
|
13888
13938
|
}
|
|
13889
13939
|
// --- Audio ---
|
|
13890
|
-
async startAudio(
|
|
13940
|
+
async startAudio() {
|
|
13891
13941
|
if (this.audioStageState !== "idle")
|
|
13892
13942
|
throw new Error("Audio capture already started");
|
|
13893
13943
|
this.audioStageState = "capturing";
|
|
13894
13944
|
this.audioController = new AbortController();
|
|
13895
13945
|
this.audioPromise = captureAudio({
|
|
13896
|
-
signal: this.audioController.signal
|
|
13897
|
-
onAudioLevel
|
|
13946
|
+
signal: this.audioController.signal
|
|
13898
13947
|
}).catch(() => null);
|
|
13899
13948
|
}
|
|
13900
13949
|
async stopAudio() {
|
|
@@ -14175,6 +14224,7 @@ function generateLissajousPoints(params) {
|
|
|
14175
14224
|
// Annotate the CommonJS export names for ESM import in node:
|
|
14176
14225
|
0 && (module.exports = {
|
|
14177
14226
|
DEFAULT_CAPTURE_MS,
|
|
14227
|
+
DEFAULT_MIN_DISTANCE,
|
|
14178
14228
|
DEFAULT_THRESHOLD,
|
|
14179
14229
|
FINGERPRINT_BITS,
|
|
14180
14230
|
MAX_CAPTURE_MS,
|
|
@@ -14182,9 +14232,11 @@ function generateLissajousPoints(params) {
|
|
|
14182
14232
|
PROGRAM_IDS,
|
|
14183
14233
|
PulseSDK,
|
|
14184
14234
|
PulseSession,
|
|
14235
|
+
autocorrelation,
|
|
14185
14236
|
bigintToBytes32,
|
|
14186
14237
|
computeCommitment,
|
|
14187
14238
|
condense,
|
|
14239
|
+
entropy,
|
|
14188
14240
|
fetchIdentityState,
|
|
14189
14241
|
fuseFeatures,
|
|
14190
14242
|
generateLissajousPoints,
|