@iam-protocol/pulse-sdk 0.2.2 → 0.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iam-protocol/pulse-sdk",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Client-side SDK for IAM Protocol — sensor capture, TBH generation, ZK proof construction",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/config.ts CHANGED
@@ -35,6 +35,7 @@ export interface PulseConfig {
35
35
  cluster: "devnet" | "mainnet-beta" | "localnet";
36
36
  rpcEndpoint?: string;
37
37
  relayerUrl?: string;
38
+ relayerApiKey?: string;
38
39
  zkeyUrl?: string;
39
40
  wasmUrl?: string;
40
41
  threshold?: number;
package/src/pulse.ts CHANGED
@@ -45,12 +45,45 @@ function extractFeatures(data: SensorData): number[] {
45
45
  * Shared pipeline: features → simhash → TBH → proof → submit.
46
46
  * Used by both PulseSDK.verify() and PulseSession.complete().
47
47
  */
48
+ // Minimum sample counts for meaningful feature extraction
49
+ const MIN_AUDIO_SAMPLES = 16000; // ~1 second at 16kHz
50
+ const MIN_MOTION_SAMPLES = 10;
51
+ const MIN_TOUCH_SAMPLES = 10;
52
+
48
53
  async function processSensorData(
49
54
  sensorData: SensorData,
50
55
  config: ResolvedConfig,
51
56
  wallet?: any,
52
57
  connection?: any
53
58
  ): Promise<VerificationResult> {
59
+ // Data quality gate: reject if insufficient behavioral data captured
60
+ const audioSamples = sensorData.audio?.samples.length ?? 0;
61
+ const motionSamples = sensorData.motion.length;
62
+ const touchSamples = sensorData.touch.length;
63
+
64
+ // Need at least audio OR (motion + touch) to produce a meaningful fingerprint
65
+ const hasAudio = audioSamples >= MIN_AUDIO_SAMPLES;
66
+ const hasMotion = motionSamples >= MIN_MOTION_SAMPLES;
67
+ const hasTouch = touchSamples >= MIN_TOUCH_SAMPLES;
68
+
69
+ if (!hasAudio && !hasMotion && !hasTouch) {
70
+ return {
71
+ success: false,
72
+ commitment: new Uint8Array(32),
73
+ isFirstVerification: true,
74
+ error: "Insufficient behavioral data. Please speak the phrase and trace the curve during capture.",
75
+ };
76
+ }
77
+
78
+ if (!hasAudio) {
79
+ return {
80
+ success: false,
81
+ commitment: new Uint8Array(32),
82
+ isFirstVerification: true,
83
+ error: "No voice data detected. Please speak the phrase clearly during capture.",
84
+ };
85
+ }
86
+
54
87
  // Extract features
55
88
  const features = extractFeatures(sensorData);
56
89
 
@@ -113,7 +146,7 @@ async function processSensorData(
113
146
  submission = await submitViaRelayer(
114
147
  solanaProof ?? { proofBytes: new Uint8Array(0), publicInputs: [] },
115
148
  tbh.commitmentBytes,
116
- { relayerUrl: config.relayerUrl, isFirstVerification }
149
+ { relayerUrl: config.relayerUrl, apiKey: config.relayerApiKey, isFirstVerification }
117
150
  );
118
151
  } else {
119
152
  return {