@veridex/sdk 1.1.4 → 1.1.6

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.js CHANGED
@@ -770,7 +770,8 @@ var init_PasskeyManager = __esm({
770
770
  credentialId: response.id,
771
771
  publicKeyX: publicKey.x,
772
772
  publicKeyY: publicKey.y,
773
- keyHash
773
+ keyHash,
774
+ assurance: _PasskeyManager.assuranceFromRegistration(response) ?? void 0
774
775
  };
775
776
  return this.credential;
776
777
  }
@@ -1149,7 +1150,8 @@ var init_PasskeyManager = __esm({
1149
1150
  credentialId: response.id,
1150
1151
  publicKeyX: publicKey.x,
1151
1152
  publicKeyY: publicKey.y,
1152
- keyHash
1153
+ keyHash,
1154
+ assurance: _PasskeyManager.assuranceFromRegistration(response) ?? void 0
1153
1155
  };
1154
1156
  this.addCredentialToStorage(backupCredential);
1155
1157
  return backupCredential;
@@ -1166,17 +1168,94 @@ var init_PasskeyManager = __esm({
1166
1168
  */
1167
1169
  static parseBackupFlags(authenticatorData) {
1168
1170
  try {
1169
- const data = import_ethers2.ethers.getBytes(authenticatorData);
1170
- if (data.length < 37) return null;
1171
- const flags = data[32];
1171
+ const assurance = _PasskeyManager.deriveAssurance(import_ethers2.ethers.getBytes(authenticatorData));
1172
+ if (!assurance) return null;
1172
1173
  return {
1173
- backupEligible: (flags & 8) !== 0,
1174
- backupState: (flags & 16) !== 0
1174
+ backupEligible: assurance.backupEligible,
1175
+ backupState: assurance.backupState
1175
1176
  };
1176
1177
  } catch {
1177
1178
  return null;
1178
1179
  }
1179
1180
  }
1181
+ /**
1182
+ * Derive credential assurance from raw WebAuthn authenticator data.
1183
+ *
1184
+ * authData layout:
1185
+ * rpIdHash (32) | flags (1) | signCount (4) | [attestedCredentialData: aaguid (16) | ...]
1186
+ *
1187
+ * Flags byte: UP 0x01 | UV 0x04 | BE 0x08 | BS 0x10 | AT 0x40 | ED 0x80
1188
+ *
1189
+ * BE is the authoritative signal for whether a credential is device-bound or
1190
+ * syncable. It is set by the authenticator itself — unlike a platform/user-agent
1191
+ * guess, it correctly identifies a hardware key used on a syncing platform.
1192
+ *
1193
+ * @returns Assurance, or `null` if authData is too short to be valid.
1194
+ */
1195
+ static deriveAssurance(authData) {
1196
+ if (authData.length < 37) return null;
1197
+ const flags = authData[32];
1198
+ const backupEligible = (flags & 8) !== 0;
1199
+ const attestedCredentialData = (flags & 64) !== 0;
1200
+ let aaguid;
1201
+ if (attestedCredentialData && authData.length >= 53) {
1202
+ aaguid = import_ethers2.ethers.hexlify(authData.slice(37, 53));
1203
+ }
1204
+ return {
1205
+ backupEligible,
1206
+ backupState: (flags & 16) !== 0,
1207
+ userVerified: (flags & 4) !== 0,
1208
+ level: backupEligible ? "synced" : "device-bound",
1209
+ aaguid
1210
+ };
1211
+ }
1212
+ /**
1213
+ * Extract raw authenticator data from a registration response.
1214
+ *
1215
+ * Prefers the `authenticatorData` field when the authenticator provides it,
1216
+ * and otherwise locates the `authData` byte string inside the CBOR
1217
+ * attestation object.
1218
+ */
1219
+ static extractAuthData(response) {
1220
+ const direct = response.response.authenticatorData;
1221
+ if (direct) {
1222
+ try {
1223
+ return base64URLDecode(direct);
1224
+ } catch {
1225
+ }
1226
+ }
1227
+ try {
1228
+ const attestationObject = base64URLDecode(response.response.attestationObject);
1229
+ let offset = 0;
1230
+ if (attestationObject[offset] >= 160 && attestationObject[offset] <= 191) {
1231
+ offset++;
1232
+ }
1233
+ const key = [104, 97, 117, 116, 104, 68, 97, 116, 97];
1234
+ let found = false;
1235
+ while (offset < attestationObject.length - 37) {
1236
+ if (key.every((byte, i) => attestationObject[offset + i] === byte)) {
1237
+ offset += key.length;
1238
+ found = true;
1239
+ break;
1240
+ }
1241
+ offset++;
1242
+ }
1243
+ if (!found) return null;
1244
+ if (attestationObject[offset] === 88) {
1245
+ offset += 2;
1246
+ } else if (attestationObject[offset] === 89) {
1247
+ offset += 3;
1248
+ }
1249
+ return attestationObject.slice(offset);
1250
+ } catch {
1251
+ return null;
1252
+ }
1253
+ }
1254
+ /** Derive assurance directly from a registration response. */
1255
+ static assuranceFromRegistration(response) {
1256
+ const authData = _PasskeyManager.extractAuthData(response);
1257
+ return authData ? _PasskeyManager.deriveAssurance(authData) : null;
1258
+ }
1180
1259
  /**
1181
1260
  * Get the number of credentials stored locally.
1182
1261
  */
@@ -12602,9 +12681,11 @@ var VeridexSDK = class {
12602
12681
  throw new VeridexError("VAULT_NOT_FOUND" /* VAULT_NOT_FOUND */, "Identity not registered. Call registerIdentity() first.");
12603
12682
  }
12604
12683
  const nonce = await this.chain.getNonce(state.identity);
12684
+ const addKeyChainConfig = this.chain.getConfig();
12685
+ const addKeyHubChainId = addKeyChainConfig.hubChainId ?? addKeyChainConfig.wormholeChainId;
12605
12686
  const packedChallenge = import_ethers15.ethers.solidityPacked(
12606
- ["string", "bytes32", "bytes32", "uint256"],
12607
- ["VERIDEX_ADD_KEY", state.identity, newCredential.keyHash, nonce]
12687
+ ["string", "bytes32", "bytes32", "uint256", "uint16"],
12688
+ ["VERIDEX_ADD_KEY", state.identity, newCredential.keyHash, nonce, addKeyHubChainId]
12608
12689
  );
12609
12690
  const signature = await this.passkey.sign(import_ethers15.ethers.getBytes(packedChallenge));
12610
12691
  if (!signer) {
@@ -12660,9 +12741,11 @@ var VeridexSDK = class {
12660
12741
  throw new VeridexError("VAULT_NOT_FOUND" /* VAULT_NOT_FOUND */, "Identity not registered. Call registerIdentity() first.");
12661
12742
  }
12662
12743
  const nonce = await this.chain.getNonce(state.identity);
12744
+ const removeKeyChainConfig = this.chain.getConfig();
12745
+ const removeKeyHubChainId = removeKeyChainConfig.hubChainId ?? removeKeyChainConfig.wormholeChainId;
12663
12746
  const packedChallenge = import_ethers15.ethers.solidityPacked(
12664
- ["string", "bytes32", "bytes32", "uint256"],
12665
- ["VERIDEX_REMOVE_KEY", state.identity, keyToRemove, nonce]
12747
+ ["string", "bytes32", "bytes32", "uint256", "uint16"],
12748
+ ["VERIDEX_REMOVE_KEY", state.identity, keyToRemove, nonce, removeKeyHubChainId]
12666
12749
  );
12667
12750
  const signature = await this.passkey.sign(import_ethers15.ethers.getBytes(packedChallenge));
12668
12751
  const { receipt, sequence } = await evmClient.removeKey(
@@ -15224,6 +15307,10 @@ init_presets();
15224
15307
  init_featureFlags();
15225
15308
  init_presets();
15226
15309
  init_featureFlags();
15310
+ var DEFAULT_PUBLIC_RELAYER_URLS = {
15311
+ testnet: "https://relayer.veridex.network"
15312
+ // mainnet: '<set when public mainnet relayer ships>',
15313
+ };
15227
15314
  function createChainClient(chain, network, customRpcUrl) {
15228
15315
  const preset = getChainPreset(chain);
15229
15316
  const config = preset[network];
@@ -15336,7 +15423,7 @@ function createSDK(chain, config = {}) {
15336
15423
  return new VeridexSDK({
15337
15424
  chain: chainClient,
15338
15425
  testnet: network === "testnet",
15339
- relayerUrl: config.relayerUrl,
15426
+ relayerUrl: config.relayerUrl ?? DEFAULT_PUBLIC_RELAYER_URLS[network],
15340
15427
  relayerApiKey: config.relayerApiKey,
15341
15428
  sponsorPrivateKey: config.sponsorPrivateKey,
15342
15429
  integratorSponsorKey: config.integratorSponsorKey,