@entros/pulse-sdk 3.3.0 → 3.4.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.mjs CHANGED
@@ -4645,6 +4645,7 @@ async function buildEd25519ReceiptIx(receipt) {
4645
4645
  }
4646
4646
 
4647
4647
  // src/identity/baseline.ts
4648
+ import { ed25519 } from "@noble/curves/ed25519";
4648
4649
  var BLOB_VERSION = 1;
4649
4650
  var ALGORITHM_AES_256_GCM = 1;
4650
4651
  var ENCRYPTED_BASELINE_BLOB_BYTES = 96;
@@ -4704,17 +4705,40 @@ async function deriveEncryptedBaselinePda(walletPubkey) {
4704
4705
  programId
4705
4706
  );
4706
4707
  }
4708
+ var WalletSignatureMismatchError = class extends Error {
4709
+ constructor(expectedWallet) {
4710
+ super(
4711
+ `signMessage did not verify against the connected wallet ${expectedWallet}. A different wallet likely signed the prompt \u2014 disable other wallet extensions or set your selected wallet as the default, then retry.`
4712
+ );
4713
+ this.name = "WalletSignatureMismatchError";
4714
+ this.expectedWallet = expectedWallet;
4715
+ }
4716
+ };
4707
4717
  async function deriveBaselineKey(wallet) {
4708
4718
  if (typeof wallet.signMessage !== "function") {
4709
4719
  throw new Error("wallet does not support signMessage");
4710
4720
  }
4711
4721
  const message = buildDomainMessage(wallet.publicKey);
4712
- const signature = await wallet.signMessage(new TextEncoder().encode(message));
4722
+ const messageBytes = new TextEncoder().encode(message);
4723
+ const signature = await wallet.signMessage(messageBytes);
4713
4724
  if (!(signature instanceof Uint8Array) || signature.length !== 64) {
4714
4725
  throw new Error(
4715
4726
  `expected 64-byte Ed25519 signature, got ${signature?.length ?? "non-Uint8Array"}`
4716
4727
  );
4717
4728
  }
4729
+ let signatureValid;
4730
+ try {
4731
+ signatureValid = ed25519.verify(
4732
+ signature,
4733
+ messageBytes,
4734
+ wallet.publicKey.toBytes()
4735
+ );
4736
+ } catch {
4737
+ signatureValid = false;
4738
+ }
4739
+ if (!signatureValid) {
4740
+ throw new WalletSignatureMismatchError(wallet.publicKey.toBase58());
4741
+ }
4718
4742
  const ikm = await crypto.subtle.importKey(
4719
4743
  "raw",
4720
4744
  signature,
@@ -5456,19 +5480,19 @@ async function fetchIdentityState(walletPubkey, connection) {
5456
5480
  const accountInfo = await connection.getAccountInfo(identityPda);
5457
5481
  if (!accountInfo) return null;
5458
5482
  const coder = new anchor.BorshAccountsCoder(entros_anchor_default);
5459
- const decoded = coder.decode("identityState", accountInfo.data);
5483
+ const decoded = coder.decode("IdentityState", accountInfo.data);
5460
5484
  return {
5461
5485
  owner: decoded.owner.toBase58(),
5462
- creationTimestamp: decoded.creationTimestamp.toNumber(),
5463
- lastVerificationTimestamp: decoded.lastVerificationTimestamp.toNumber(),
5464
- verificationCount: decoded.verificationCount,
5465
- trustScore: decoded.trustScore,
5466
- currentCommitment: new Uint8Array(decoded.currentCommitment),
5486
+ creationTimestamp: decoded.creation_timestamp.toNumber(),
5487
+ lastVerificationTimestamp: decoded.last_verification_timestamp.toNumber(),
5488
+ verificationCount: decoded.verification_count,
5489
+ trustScore: decoded.trust_score,
5490
+ currentCommitment: new Uint8Array(decoded.current_commitment),
5467
5491
  mint: decoded.mint.toBase58(),
5468
5492
  // Anchor's Borsh coder returns the raw BN for i64 fields; .toNumber()
5469
5493
  // is safe here because Unix timestamps fit in Number.MAX_SAFE_INTEGER
5470
5494
  // until year 275760.
5471
- lastResetTimestamp: decoded.lastResetTimestamp?.toNumber?.() ?? 0
5495
+ lastResetTimestamp: decoded.last_reset_timestamp?.toNumber?.() ?? 0
5472
5496
  };
5473
5497
  } catch {
5474
5498
  return null;
@@ -5570,6 +5594,13 @@ async function recoverBaselineFromChain(wallet, connection) {
5570
5594
  key = await getOrDeriveBaselineKey(wallet);
5571
5595
  } catch (err) {
5572
5596
  const detail = err instanceof Error ? err.message : String(err);
5597
+ if (err instanceof WalletSignatureMismatchError) {
5598
+ return {
5599
+ recovered: false,
5600
+ reason: "wallet-mismatch",
5601
+ detail
5602
+ };
5603
+ }
5573
5604
  return {
5574
5605
  recovered: false,
5575
5606
  reason: "signing-unavailable",
@@ -5849,6 +5880,7 @@ async function processSensorData(sensorData, config, wallet, connection, onProgr
5849
5880
  } else {
5850
5881
  isFirstVerification = !previousData;
5851
5882
  }
5883
+ let walletMismatch = false;
5852
5884
  if (!isFirstVerification && !previousData && wallet && connection) {
5853
5885
  const baselineWallet = resolveBaselineWallet(wallet);
5854
5886
  if (baselineWallet) {
@@ -5858,6 +5890,7 @@ async function processSensorData(sensorData, config, wallet, connection, onProgr
5858
5890
  previousData = await loadVerificationData();
5859
5891
  sdkLog("[Entros SDK] On-chain encrypted baseline recovered");
5860
5892
  } else {
5893
+ walletMismatch = recovery.reason === "wallet-mismatch";
5861
5894
  sdkLog(
5862
5895
  `[Entros SDK] On-chain encrypted baseline recovery not available (${recovery.reason ?? "unknown"})`
5863
5896
  );
@@ -5865,6 +5898,14 @@ async function processSensorData(sensorData, config, wallet, connection, onProgr
5865
5898
  }
5866
5899
  }
5867
5900
  if (!isFirstVerification && !previousData) {
5901
+ if (walletMismatch) {
5902
+ return {
5903
+ success: false,
5904
+ commitment: tbh.commitmentBytes,
5905
+ isFirstVerification: false,
5906
+ error: "A different wallet signed than the one connected. Another wallet extension likely intercepted the signature prompt. Sign with your connected wallet, or disable other wallet extensions (or unset their default), then try again."
5907
+ };
5908
+ }
5868
5909
  return {
5869
5910
  success: false,
5870
5911
  commitment: tbh.commitmentBytes,
@@ -6951,6 +6992,7 @@ export {
6951
6992
  SPEAKER_FEATURE_COUNT,
6952
6993
  StaleEncryptedBaselineError,
6953
6994
  TOUCH_FEATURE_COUNT,
6995
+ WalletSignatureMismatchError,
6954
6996
  attestAgentOperator,
6955
6997
  bigintToBytes32,
6956
6998
  bytes32ToBigint,