@volr/react 0.1.112 → 0.1.113
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.cjs +162 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +162 -19
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -19401,6 +19401,11 @@ function useDepositListener(input) {
|
|
|
19401
19401
|
}, [getRpcUrl, input.chainId, input.address, JSON.stringify(input.asset)]);
|
|
19402
19402
|
return status;
|
|
19403
19403
|
}
|
|
19404
|
+
function debugLog(step, data) {
|
|
19405
|
+
{
|
|
19406
|
+
console.log(`[PasskeyEnrollment] ${step}`, data !== void 0 ? data : "");
|
|
19407
|
+
}
|
|
19408
|
+
}
|
|
19404
19409
|
function blobToBase64(blob) {
|
|
19405
19410
|
return new Promise((resolve, reject) => {
|
|
19406
19411
|
const reader = new FileReader();
|
|
@@ -19448,6 +19453,14 @@ function buildDisplayName(userEmail, userEvmAddress, userId) {
|
|
|
19448
19453
|
return userId || "Volr Wallet";
|
|
19449
19454
|
}
|
|
19450
19455
|
async function enrollPasskey(params) {
|
|
19456
|
+
debugLog("Starting enrollment with params:", {
|
|
19457
|
+
userId: params.userId,
|
|
19458
|
+
projectId: params.projectId,
|
|
19459
|
+
rpId: params.rpId,
|
|
19460
|
+
rpName: params.rpName,
|
|
19461
|
+
userEmail: params.userEmail,
|
|
19462
|
+
userEvmAddress: params.userEvmAddress
|
|
19463
|
+
});
|
|
19451
19464
|
const {
|
|
19452
19465
|
client,
|
|
19453
19466
|
baseUrl,
|
|
@@ -19459,6 +19472,7 @@ async function enrollPasskey(params) {
|
|
|
19459
19472
|
rpId = typeof window !== "undefined" ? window.location.hostname : "localhost",
|
|
19460
19473
|
rpName
|
|
19461
19474
|
} = params;
|
|
19475
|
+
debugLog("Step 0: Validating parameters");
|
|
19462
19476
|
if (!userId) {
|
|
19463
19477
|
throw new Error("userId is required");
|
|
19464
19478
|
}
|
|
@@ -19474,19 +19488,27 @@ async function enrollPasskey(params) {
|
|
|
19474
19488
|
if (!apiKey) {
|
|
19475
19489
|
throw new Error("apiKey is required");
|
|
19476
19490
|
}
|
|
19491
|
+
debugLog("Step 0: Parameters validated", { rpId, rpName });
|
|
19492
|
+
debugLog("Step 1: Checking WebAuthn support");
|
|
19477
19493
|
if (!navigator.credentials || !navigator.credentials.create) {
|
|
19478
19494
|
throw new Error("WebAuthn API is not supported");
|
|
19479
19495
|
}
|
|
19496
|
+
debugLog("Step 1: WebAuthn API is supported");
|
|
19480
19497
|
const challenge2 = new Uint8Array(32);
|
|
19481
19498
|
crypto.getRandomValues(challenge2);
|
|
19499
|
+
debugLog("Step 1: Challenge generated", { challengeLength: challenge2.length });
|
|
19482
19500
|
const userHandle = new TextEncoder().encode(userId);
|
|
19501
|
+
debugLog("Step 1: User handle created", { userHandleLength: userHandle.length });
|
|
19483
19502
|
const tempCredentialId = "temp-" + Date.now();
|
|
19484
19503
|
const tempPrfInput = {
|
|
19485
19504
|
projectId,
|
|
19486
19505
|
credentialId: tempCredentialId
|
|
19487
19506
|
};
|
|
19507
|
+
debugLog("Step 1: Temp PRF input created", tempPrfInput);
|
|
19488
19508
|
const prfSalt = deriveWrapKey(tempPrfInput);
|
|
19509
|
+
debugLog("Step 1: PRF salt derived", { prfSaltLength: prfSalt.length });
|
|
19489
19510
|
const displayName = buildDisplayName(userEmail, userEvmAddress, userId);
|
|
19511
|
+
debugLog("Step 1: Display name built", { displayName });
|
|
19490
19512
|
const publicKeyCredentialCreationOptions = {
|
|
19491
19513
|
challenge: challenge2,
|
|
19492
19514
|
rp: {
|
|
@@ -19510,37 +19532,105 @@ async function enrollPasskey(params) {
|
|
|
19510
19532
|
}
|
|
19511
19533
|
}
|
|
19512
19534
|
};
|
|
19513
|
-
|
|
19514
|
-
|
|
19535
|
+
debugLog("Step 1: WebAuthn options prepared", {
|
|
19536
|
+
rpId: publicKeyCredentialCreationOptions.rp.id,
|
|
19537
|
+
rpName: publicKeyCredentialCreationOptions.rp.name,
|
|
19538
|
+
timeout: publicKeyCredentialCreationOptions.timeout,
|
|
19539
|
+
attestation: publicKeyCredentialCreationOptions.attestation,
|
|
19540
|
+
authenticatorSelection: publicKeyCredentialCreationOptions.authenticatorSelection,
|
|
19541
|
+
pubKeyCredParams: publicKeyCredentialCreationOptions.pubKeyCredParams
|
|
19515
19542
|
});
|
|
19543
|
+
debugLog("Step 1: Calling navigator.credentials.create()...");
|
|
19544
|
+
let credential;
|
|
19545
|
+
try {
|
|
19546
|
+
credential = await navigator.credentials.create({
|
|
19547
|
+
publicKey: publicKeyCredentialCreationOptions
|
|
19548
|
+
});
|
|
19549
|
+
debugLog("Step 1: Credential creation completed", {
|
|
19550
|
+
hasCredential: !!credential,
|
|
19551
|
+
credentialId: credential ? Array.from(new Uint8Array(credential.rawId)).slice(0, 8).join(",") + "..." : null
|
|
19552
|
+
});
|
|
19553
|
+
} catch (err) {
|
|
19554
|
+
debugLog("Step 1: Credential creation FAILED", {
|
|
19555
|
+
error: err,
|
|
19556
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
19557
|
+
errorName: err instanceof Error ? err.name : "Unknown"
|
|
19558
|
+
});
|
|
19559
|
+
throw err;
|
|
19560
|
+
}
|
|
19516
19561
|
if (!credential || !("response" in credential)) {
|
|
19562
|
+
debugLog("Step 1: Invalid credential response", { credential });
|
|
19517
19563
|
throw new Error("Failed to create passkey credential");
|
|
19518
19564
|
}
|
|
19519
19565
|
const credentialId = Array.from(new Uint8Array(credential.rawId)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
19566
|
+
debugLog("Step 2: Credential ID extracted", { credentialIdLength: credentialId.length, credentialIdPrefix: credentialId.slice(0, 16) });
|
|
19567
|
+
debugLog("Step 2: Extracting PRF output");
|
|
19520
19568
|
const extensionResults = credential.getClientExtensionResults();
|
|
19569
|
+
debugLog("Step 2: Extension results", {
|
|
19570
|
+
hasExtensionResults: !!extensionResults,
|
|
19571
|
+
hasPrf: !!extensionResults.prf,
|
|
19572
|
+
hasPrfResults: !!(extensionResults.prf && extensionResults.prf.results),
|
|
19573
|
+
hasPrfFirst: !!(extensionResults.prf && extensionResults.prf.results && extensionResults.prf.results.first),
|
|
19574
|
+
allKeys: Object.keys(extensionResults)
|
|
19575
|
+
});
|
|
19521
19576
|
if (!extensionResults.prf || !extensionResults.prf.results || !extensionResults.prf.results.first) {
|
|
19577
|
+
debugLog("Step 2: PRF extension not supported or missing", extensionResults);
|
|
19522
19578
|
throw new Error("PRF extension not supported or PRF output missing. Please use a browser that supports WebAuthn PRF extension.");
|
|
19523
19579
|
}
|
|
19524
19580
|
const prfOutputBuffer = extensionResults.prf.results.first;
|
|
19525
19581
|
const prfOutput = new Uint8Array(prfOutputBuffer);
|
|
19582
|
+
debugLog("Step 2: PRF output extracted", { prfOutputLength: prfOutput.length });
|
|
19526
19583
|
const prfInput = {
|
|
19527
19584
|
projectId,
|
|
19528
19585
|
credentialId
|
|
19529
19586
|
};
|
|
19587
|
+
debugLog("Step 3: PRF input built", prfInput);
|
|
19530
19588
|
const wrapKey = prfOutput;
|
|
19589
|
+
debugLog("Step 4: Wrap key created from PRF output", { wrapKeyLength: wrapKey.length });
|
|
19590
|
+
debugLog("Step 4: Generating master key...");
|
|
19531
19591
|
const masterKeyProvider = createMasterKeyProvider();
|
|
19532
|
-
|
|
19592
|
+
let masterKeyHandle;
|
|
19593
|
+
try {
|
|
19594
|
+
masterKeyHandle = await masterKeyProvider.generate();
|
|
19595
|
+
debugLog("Step 4: Master key generated", {
|
|
19596
|
+
hasEntropy: !!masterKeyHandle.entropy,
|
|
19597
|
+
entropyLength: masterKeyHandle.entropy?.length,
|
|
19598
|
+
hasSeed: !!masterKeyHandle.seed,
|
|
19599
|
+
seedLength: masterKeyHandle.seed?.length
|
|
19600
|
+
});
|
|
19601
|
+
} catch (err) {
|
|
19602
|
+
debugLog("Step 4: Master key generation FAILED", {
|
|
19603
|
+
error: err,
|
|
19604
|
+
errorMessage: err instanceof Error ? err.message : String(err)
|
|
19605
|
+
});
|
|
19606
|
+
throw err;
|
|
19607
|
+
}
|
|
19533
19608
|
try {
|
|
19534
19609
|
const keyStorageType = "passkey";
|
|
19535
19610
|
const version5 = "v1";
|
|
19536
19611
|
const aadBytes = new TextEncoder().encode(
|
|
19537
19612
|
`volr/master-seed/v1|${userId}|${keyStorageType}|${version5}`
|
|
19538
19613
|
);
|
|
19539
|
-
|
|
19540
|
-
|
|
19541
|
-
|
|
19542
|
-
|
|
19543
|
-
|
|
19614
|
+
debugLog("Step 4: AAD built", { aadLength: aadBytes.length });
|
|
19615
|
+
debugLog("Step 4: Encrypting entropy...");
|
|
19616
|
+
let encryptedBlob;
|
|
19617
|
+
try {
|
|
19618
|
+
encryptedBlob = await sealMasterSeed(
|
|
19619
|
+
masterKeyHandle.entropy,
|
|
19620
|
+
wrapKey,
|
|
19621
|
+
aadBytes
|
|
19622
|
+
);
|
|
19623
|
+
debugLog("Step 4: Entropy encrypted", {
|
|
19624
|
+
cipherLength: encryptedBlob.cipher.length,
|
|
19625
|
+
nonceLength: encryptedBlob.nonce.length
|
|
19626
|
+
});
|
|
19627
|
+
} catch (err) {
|
|
19628
|
+
debugLog("Step 4: Encryption FAILED", {
|
|
19629
|
+
error: err,
|
|
19630
|
+
errorMessage: err instanceof Error ? err.message : String(err)
|
|
19631
|
+
});
|
|
19632
|
+
throw err;
|
|
19633
|
+
}
|
|
19544
19634
|
const blob = new Blob(
|
|
19545
19635
|
[
|
|
19546
19636
|
encryptedBlob.cipher,
|
|
@@ -19550,28 +19640,80 @@ async function enrollPasskey(params) {
|
|
|
19550
19640
|
type: "application/octet-stream"
|
|
19551
19641
|
}
|
|
19552
19642
|
);
|
|
19643
|
+
debugLog("Step 5: Blob prepared", { blobSize: blob.size });
|
|
19644
|
+
debugLog("Step 6: Converting blob to base64...");
|
|
19553
19645
|
const blobB64 = await blobToBase64(blob);
|
|
19554
|
-
|
|
19555
|
-
|
|
19556
|
-
|
|
19646
|
+
debugLog("Step 6: Blob converted", { blobB64Length: blobB64.length });
|
|
19647
|
+
debugLog("Step 6: Uploading blob...");
|
|
19648
|
+
let uploadResponse;
|
|
19649
|
+
try {
|
|
19650
|
+
uploadResponse = await client.post("/blob/upload", {
|
|
19651
|
+
blobB64
|
|
19652
|
+
});
|
|
19653
|
+
debugLog("Step 6: Upload response", uploadResponse);
|
|
19654
|
+
} catch (err) {
|
|
19655
|
+
debugLog("Step 6: Blob upload FAILED", {
|
|
19656
|
+
error: err,
|
|
19657
|
+
errorMessage: err instanceof Error ? err.message : String(err)
|
|
19658
|
+
});
|
|
19659
|
+
throw err;
|
|
19660
|
+
}
|
|
19557
19661
|
const blobUrl = uploadResponse?.key;
|
|
19558
19662
|
if (!blobUrl) {
|
|
19663
|
+
debugLog("Step 6: Missing blob URL in response", uploadResponse);
|
|
19559
19664
|
throw new Error("Failed to upload blob: missing key");
|
|
19560
19665
|
}
|
|
19561
|
-
|
|
19666
|
+
debugLog("Step 6: Blob uploaded", { blobUrl });
|
|
19667
|
+
debugLog("Step 7: Deriving address from seed...");
|
|
19668
|
+
let keypair;
|
|
19669
|
+
try {
|
|
19670
|
+
keypair = deriveEvmKey({ masterSeed: masterKeyHandle.seed });
|
|
19671
|
+
debugLog("Step 7: Keypair derived", { address: keypair.address });
|
|
19672
|
+
} catch (err) {
|
|
19673
|
+
debugLog("Step 7: Key derivation FAILED", {
|
|
19674
|
+
error: err,
|
|
19675
|
+
errorMessage: err instanceof Error ? err.message : String(err)
|
|
19676
|
+
});
|
|
19677
|
+
throw err;
|
|
19678
|
+
}
|
|
19562
19679
|
const address = keypair.address;
|
|
19563
19680
|
const platform = detectPlatform();
|
|
19564
|
-
|
|
19681
|
+
debugLog("Step 8: Registering provider...", {
|
|
19565
19682
|
keyStorageType: "passkey",
|
|
19566
19683
|
credentialId,
|
|
19567
19684
|
blobUrl,
|
|
19568
|
-
prfInput: {
|
|
19569
|
-
projectId,
|
|
19570
|
-
credentialId
|
|
19571
|
-
},
|
|
19572
19685
|
address,
|
|
19573
19686
|
platform
|
|
19574
|
-
|
|
19687
|
+
});
|
|
19688
|
+
let registerResponse;
|
|
19689
|
+
try {
|
|
19690
|
+
registerResponse = await client.post("/wallet/provider/register", {
|
|
19691
|
+
keyStorageType: "passkey",
|
|
19692
|
+
credentialId,
|
|
19693
|
+
blobUrl,
|
|
19694
|
+
prfInput: {
|
|
19695
|
+
projectId,
|
|
19696
|
+
credentialId
|
|
19697
|
+
},
|
|
19698
|
+
address,
|
|
19699
|
+
platform
|
|
19700
|
+
// For UX hints when authenticating on different devices
|
|
19701
|
+
});
|
|
19702
|
+
debugLog("Step 8: Provider registered", {
|
|
19703
|
+
providerId: registerResponse?.id,
|
|
19704
|
+
hasUser: !!registerResponse?.user
|
|
19705
|
+
});
|
|
19706
|
+
} catch (err) {
|
|
19707
|
+
debugLog("Step 8: Provider registration FAILED", {
|
|
19708
|
+
error: err,
|
|
19709
|
+
errorMessage: err instanceof Error ? err.message : String(err)
|
|
19710
|
+
});
|
|
19711
|
+
throw err;
|
|
19712
|
+
}
|
|
19713
|
+
debugLog("Enrollment completed successfully!", {
|
|
19714
|
+
credentialId,
|
|
19715
|
+
blobUrl,
|
|
19716
|
+
address
|
|
19575
19717
|
});
|
|
19576
19718
|
return {
|
|
19577
19719
|
credentialId,
|
|
@@ -19586,7 +19728,8 @@ async function enrollPasskey(params) {
|
|
|
19586
19728
|
user: registerResponse.user
|
|
19587
19729
|
};
|
|
19588
19730
|
} finally {
|
|
19589
|
-
|
|
19731
|
+
debugLog("Cleanup: Destroying master key handle");
|
|
19732
|
+
masterKeyHandle.destroy();
|
|
19590
19733
|
}
|
|
19591
19734
|
}
|
|
19592
19735
|
function usePasskeyEnrollment() {
|