@volr/react 0.1.90 → 0.1.92
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 +259 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +144 -2
- package/dist/index.d.ts +144 -2
- package/dist/index.js +254 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -9781,7 +9781,9 @@ async function restorePasskey(params) {
|
|
|
9781
9781
|
userId,
|
|
9782
9782
|
blobUrl,
|
|
9783
9783
|
prfInput,
|
|
9784
|
-
credentialId: providedCredentialId
|
|
9784
|
+
credentialId: providedCredentialId,
|
|
9785
|
+
rpId = typeof window !== "undefined" ? window.location.hostname : "localhost",
|
|
9786
|
+
rpName = "Volr"
|
|
9785
9787
|
} = params;
|
|
9786
9788
|
const credentialId = providedCredentialId || prfInput.credentialId || safeStorage.getItem(STORAGE_KEYS.credentialId);
|
|
9787
9789
|
if (!credentialId) {
|
|
@@ -9810,7 +9812,7 @@ async function restorePasskey(params) {
|
|
|
9810
9812
|
`volr/master-seed/v1|${userId}|${keyStorageType}|${version5}`
|
|
9811
9813
|
);
|
|
9812
9814
|
const passkeyAdapter = createPasskeyAdapter({
|
|
9813
|
-
rpId
|
|
9815
|
+
rpId});
|
|
9814
9816
|
const provider = sdkCore.createPasskeyProvider(passkeyAdapter, {
|
|
9815
9817
|
prfInput: {
|
|
9816
9818
|
...prfInput,
|
|
@@ -18701,6 +18703,8 @@ function useVolrLogin() {
|
|
|
18701
18703
|
const toVolrUser = react.useCallback((u) => {
|
|
18702
18704
|
return {
|
|
18703
18705
|
id: u.id,
|
|
18706
|
+
projectId: u.projectId,
|
|
18707
|
+
projectName: u.projectName,
|
|
18704
18708
|
email: u.email,
|
|
18705
18709
|
accountId: u.accountId ?? void 0,
|
|
18706
18710
|
evmAddress: u.evmAddress,
|
|
@@ -18916,6 +18920,8 @@ function useVolrAuthCallback(options = {}) {
|
|
|
18916
18920
|
const toVolrUser = react.useCallback((u) => {
|
|
18917
18921
|
return {
|
|
18918
18922
|
id: u.id,
|
|
18923
|
+
projectId: u.projectId,
|
|
18924
|
+
projectName: u.projectName,
|
|
18919
18925
|
email: u.email,
|
|
18920
18926
|
accountId: u.accountId ?? void 0,
|
|
18921
18927
|
evmAddress: u.evmAddress,
|
|
@@ -19182,7 +19188,7 @@ async function enrollPasskey(params) {
|
|
|
19182
19188
|
userEvmAddress,
|
|
19183
19189
|
projectId,
|
|
19184
19190
|
rpId = typeof window !== "undefined" ? window.location.hostname : "localhost",
|
|
19185
|
-
rpName
|
|
19191
|
+
rpName
|
|
19186
19192
|
} = params;
|
|
19187
19193
|
if (!userId) {
|
|
19188
19194
|
throw new Error("userId is required");
|
|
@@ -19190,6 +19196,9 @@ async function enrollPasskey(params) {
|
|
|
19190
19196
|
if (!projectId) {
|
|
19191
19197
|
throw new Error("projectId is required");
|
|
19192
19198
|
}
|
|
19199
|
+
if (!rpName) {
|
|
19200
|
+
throw new Error("rpName is required");
|
|
19201
|
+
}
|
|
19193
19202
|
if (!baseUrl) {
|
|
19194
19203
|
throw new Error("baseUrl is required");
|
|
19195
19204
|
}
|
|
@@ -19203,9 +19212,7 @@ async function enrollPasskey(params) {
|
|
|
19203
19212
|
crypto.getRandomValues(challenge2);
|
|
19204
19213
|
const userHandle = new TextEncoder().encode(userId);
|
|
19205
19214
|
const tempCredentialId = "temp-" + Date.now();
|
|
19206
|
-
const origin = typeof window !== "undefined" ? window.location.origin : "https://localhost";
|
|
19207
19215
|
const tempPrfInput = {
|
|
19208
|
-
origin,
|
|
19209
19216
|
projectId,
|
|
19210
19217
|
credentialId: tempCredentialId
|
|
19211
19218
|
};
|
|
@@ -19248,7 +19255,6 @@ async function enrollPasskey(params) {
|
|
|
19248
19255
|
const prfOutputBuffer = extensionResults.prf.results.first;
|
|
19249
19256
|
const prfOutput = new Uint8Array(prfOutputBuffer);
|
|
19250
19257
|
const prfInput = {
|
|
19251
|
-
origin,
|
|
19252
19258
|
projectId,
|
|
19253
19259
|
credentialId
|
|
19254
19260
|
};
|
|
@@ -19284,7 +19290,6 @@ async function enrollPasskey(params) {
|
|
|
19284
19290
|
apiKey,
|
|
19285
19291
|
accessToken,
|
|
19286
19292
|
blob
|
|
19287
|
-
// Don't pass axiosInstance - let uploadBlob create its own
|
|
19288
19293
|
});
|
|
19289
19294
|
if (!blobUrl) {
|
|
19290
19295
|
throw new Error("Failed to upload blob: missing key");
|
|
@@ -19297,7 +19302,6 @@ async function enrollPasskey(params) {
|
|
|
19297
19302
|
credentialId,
|
|
19298
19303
|
blobUrl,
|
|
19299
19304
|
prfInput: {
|
|
19300
|
-
origin,
|
|
19301
19305
|
projectId,
|
|
19302
19306
|
credentialId
|
|
19303
19307
|
},
|
|
@@ -19345,7 +19349,17 @@ function usePasskeyEnrollment() {
|
|
|
19345
19349
|
"Access token is required for passkey enrollment. Please login first."
|
|
19346
19350
|
);
|
|
19347
19351
|
}
|
|
19348
|
-
|
|
19352
|
+
if (!user.projectId) {
|
|
19353
|
+
throw new Error(
|
|
19354
|
+
"Project ID is required for passkey enrollment. User data may be incomplete."
|
|
19355
|
+
);
|
|
19356
|
+
}
|
|
19357
|
+
if (!user.projectName) {
|
|
19358
|
+
throw new Error(
|
|
19359
|
+
"Project name is required for passkey enrollment. User data may be incomplete."
|
|
19360
|
+
);
|
|
19361
|
+
}
|
|
19362
|
+
const projectId = user.projectId;
|
|
19349
19363
|
setStep("encrypting");
|
|
19350
19364
|
const result = await enrollPasskey({
|
|
19351
19365
|
client,
|
|
@@ -19354,7 +19368,8 @@ function usePasskeyEnrollment() {
|
|
|
19354
19368
|
userId: user.id,
|
|
19355
19369
|
userEmail: user.email ?? null,
|
|
19356
19370
|
userEvmAddress: user.evmAddress ?? null,
|
|
19357
|
-
projectId
|
|
19371
|
+
projectId,
|
|
19372
|
+
rpName: user.projectName
|
|
19358
19373
|
});
|
|
19359
19374
|
setStep("registering");
|
|
19360
19375
|
if (typeof window !== "undefined") {
|
|
@@ -19362,7 +19377,7 @@ function usePasskeyEnrollment() {
|
|
|
19362
19377
|
}
|
|
19363
19378
|
const passkeyAdapter = createPasskeyAdapter({
|
|
19364
19379
|
rpId: typeof window !== "undefined" ? window.location.hostname : "localhost",
|
|
19365
|
-
rpName:
|
|
19380
|
+
rpName: user.projectName
|
|
19366
19381
|
});
|
|
19367
19382
|
const provider = sdkCore.createPasskeyProvider(passkeyAdapter, {
|
|
19368
19383
|
prfInput: result.prfInput,
|
|
@@ -19971,6 +19986,232 @@ async function checkPrfExtensionAvailable() {
|
|
|
19971
19986
|
const { prfSupported } = checkPrfSupport();
|
|
19972
19987
|
return prfSupported;
|
|
19973
19988
|
}
|
|
19989
|
+
async function requestMigration(params) {
|
|
19990
|
+
const { client, targetOrigin } = params;
|
|
19991
|
+
const response = await client.post("/wallet/migration/request", { targetOrigin });
|
|
19992
|
+
return {
|
|
19993
|
+
migrationToken: response.migrationToken,
|
|
19994
|
+
targetOrigin: response.targetOrigin,
|
|
19995
|
+
expiresAt: response.expiresAt
|
|
19996
|
+
};
|
|
19997
|
+
}
|
|
19998
|
+
function openMigrationPopup(targetOrigin, migrationToken, migrationPath = "/wallet/migrate") {
|
|
19999
|
+
const url = new URL(migrationPath, targetOrigin);
|
|
20000
|
+
url.searchParams.set("migration_token", migrationToken);
|
|
20001
|
+
const width = 500;
|
|
20002
|
+
const height = 600;
|
|
20003
|
+
const left = window.screenX + (window.outerWidth - width) / 2;
|
|
20004
|
+
const top = window.screenY + (window.outerHeight - height) / 2;
|
|
20005
|
+
return window.open(
|
|
20006
|
+
url.toString(),
|
|
20007
|
+
"volr_migration",
|
|
20008
|
+
`width=${width},height=${height},left=${left},top=${top},popup=1`
|
|
20009
|
+
);
|
|
20010
|
+
}
|
|
20011
|
+
function sendSeedToPopup(masterSeed, userId, projectId, targetOrigin, popup) {
|
|
20012
|
+
const response = {
|
|
20013
|
+
type: "VOLR_MIGRATION_SEED_RESPONSE",
|
|
20014
|
+
masterSeed: Array.from(masterSeed),
|
|
20015
|
+
userId,
|
|
20016
|
+
projectId
|
|
20017
|
+
};
|
|
20018
|
+
popup.postMessage(response, targetOrigin);
|
|
20019
|
+
}
|
|
20020
|
+
function listenForSeedRequests(allowedOrigins, getMasterSeed, getUserInfo) {
|
|
20021
|
+
const handleMessage = async (event) => {
|
|
20022
|
+
if (!allowedOrigins.includes(event.origin)) {
|
|
20023
|
+
return;
|
|
20024
|
+
}
|
|
20025
|
+
const data = event.data;
|
|
20026
|
+
if (data?.type !== "VOLR_MIGRATION_SEED_REQUEST") {
|
|
20027
|
+
return;
|
|
20028
|
+
}
|
|
20029
|
+
try {
|
|
20030
|
+
const masterSeed = await getMasterSeed();
|
|
20031
|
+
const { userId, projectId } = getUserInfo();
|
|
20032
|
+
const response = {
|
|
20033
|
+
type: "VOLR_MIGRATION_SEED_RESPONSE",
|
|
20034
|
+
masterSeed: Array.from(masterSeed),
|
|
20035
|
+
userId,
|
|
20036
|
+
projectId
|
|
20037
|
+
};
|
|
20038
|
+
event.source?.postMessage(response, { targetOrigin: event.origin });
|
|
20039
|
+
} catch (error) {
|
|
20040
|
+
const errorResponse = {
|
|
20041
|
+
type: "VOLR_MIGRATION_ERROR",
|
|
20042
|
+
code: "SEED_RETRIEVAL_FAILED",
|
|
20043
|
+
message: error instanceof Error ? error.message : "Failed to retrieve master seed"
|
|
20044
|
+
};
|
|
20045
|
+
event.source?.postMessage(errorResponse, { targetOrigin: event.origin });
|
|
20046
|
+
}
|
|
20047
|
+
};
|
|
20048
|
+
window.addEventListener("message", handleMessage);
|
|
20049
|
+
return () => {
|
|
20050
|
+
window.removeEventListener("message", handleMessage);
|
|
20051
|
+
};
|
|
20052
|
+
}
|
|
20053
|
+
function requestSeedFromOpener(sourceOrigin, migrationToken, timeout = 6e4) {
|
|
20054
|
+
return new Promise((resolve, reject) => {
|
|
20055
|
+
if (!window.opener) {
|
|
20056
|
+
reject(new Error("No opener window found. This page must be opened as a popup."));
|
|
20057
|
+
return;
|
|
20058
|
+
}
|
|
20059
|
+
const timeoutId = setTimeout(() => {
|
|
20060
|
+
window.removeEventListener("message", handleMessage);
|
|
20061
|
+
reject(new Error("Seed request timed out"));
|
|
20062
|
+
}, timeout);
|
|
20063
|
+
const handleMessage = (event) => {
|
|
20064
|
+
if (event.origin !== sourceOrigin) {
|
|
20065
|
+
return;
|
|
20066
|
+
}
|
|
20067
|
+
const data = event.data;
|
|
20068
|
+
if (data?.type === "VOLR_MIGRATION_SEED_RESPONSE") {
|
|
20069
|
+
clearTimeout(timeoutId);
|
|
20070
|
+
window.removeEventListener("message", handleMessage);
|
|
20071
|
+
resolve({
|
|
20072
|
+
masterSeed: new Uint8Array(data.masterSeed),
|
|
20073
|
+
userId: data.userId,
|
|
20074
|
+
projectId: data.projectId
|
|
20075
|
+
});
|
|
20076
|
+
} else if (data?.type === "VOLR_MIGRATION_ERROR") {
|
|
20077
|
+
clearTimeout(timeoutId);
|
|
20078
|
+
window.removeEventListener("message", handleMessage);
|
|
20079
|
+
reject(new Error(`${data.code}: ${data.message}`));
|
|
20080
|
+
}
|
|
20081
|
+
};
|
|
20082
|
+
window.addEventListener("message", handleMessage);
|
|
20083
|
+
const request = {
|
|
20084
|
+
type: "VOLR_MIGRATION_SEED_REQUEST",
|
|
20085
|
+
migrationToken
|
|
20086
|
+
};
|
|
20087
|
+
window.opener.postMessage(request, sourceOrigin);
|
|
20088
|
+
});
|
|
20089
|
+
}
|
|
20090
|
+
function detectPlatform3() {
|
|
20091
|
+
if (typeof navigator === "undefined") return "Unknown";
|
|
20092
|
+
const ua = navigator.userAgent;
|
|
20093
|
+
const platform = navigator.platform || "";
|
|
20094
|
+
if (/iPhone|iPad|iPod/.test(ua) || platform === "MacIntel" && navigator.maxTouchPoints > 1) {
|
|
20095
|
+
return "iOS";
|
|
20096
|
+
}
|
|
20097
|
+
if (/Android/.test(ua)) return "Android";
|
|
20098
|
+
if (/Mac/.test(platform)) return "macOS";
|
|
20099
|
+
if (/Win/.test(platform)) return "Windows";
|
|
20100
|
+
if (/CrOS/.test(ua)) return "ChromeOS";
|
|
20101
|
+
if (/Linux/.test(platform)) return "Linux";
|
|
20102
|
+
return "Unknown";
|
|
20103
|
+
}
|
|
20104
|
+
async function completeMigration(params) {
|
|
20105
|
+
const {
|
|
20106
|
+
client,
|
|
20107
|
+
baseUrl,
|
|
20108
|
+
apiKey,
|
|
20109
|
+
userId,
|
|
20110
|
+
projectId,
|
|
20111
|
+
migrationToken,
|
|
20112
|
+
masterSeed,
|
|
20113
|
+
rpId = typeof window !== "undefined" ? window.location.hostname : "localhost",
|
|
20114
|
+
rpName = "Volr",
|
|
20115
|
+
userEmail
|
|
20116
|
+
} = params;
|
|
20117
|
+
if (!navigator.credentials || !navigator.credentials.create) {
|
|
20118
|
+
throw new Error("WebAuthn API is not supported");
|
|
20119
|
+
}
|
|
20120
|
+
const challenge2 = new Uint8Array(32);
|
|
20121
|
+
crypto.getRandomValues(challenge2);
|
|
20122
|
+
const userHandle = new TextEncoder().encode(userId);
|
|
20123
|
+
const displayName = userEmail || `Volr Wallet (${userId.substring(0, 8)}...)`;
|
|
20124
|
+
const tempCredentialId = "temp-" + Date.now();
|
|
20125
|
+
const tempPrfInput = {
|
|
20126
|
+
projectId,
|
|
20127
|
+
credentialId: tempCredentialId
|
|
20128
|
+
};
|
|
20129
|
+
const prfSalt = sdkCore.deriveWrapKey(tempPrfInput);
|
|
20130
|
+
const publicKeyCredentialCreationOptions = {
|
|
20131
|
+
challenge: challenge2,
|
|
20132
|
+
rp: {
|
|
20133
|
+
name: rpName,
|
|
20134
|
+
id: rpId
|
|
20135
|
+
},
|
|
20136
|
+
user: {
|
|
20137
|
+
id: userHandle,
|
|
20138
|
+
name: displayName,
|
|
20139
|
+
displayName
|
|
20140
|
+
},
|
|
20141
|
+
pubKeyCredParams: PUBKEY_CRED_PARAMS,
|
|
20142
|
+
authenticatorSelection: AUTHENTICATOR_SELECTION,
|
|
20143
|
+
timeout: WEBAUTHN_TIMEOUT,
|
|
20144
|
+
attestation: ATTESTATION,
|
|
20145
|
+
extensions: {
|
|
20146
|
+
prf: {
|
|
20147
|
+
eval: {
|
|
20148
|
+
first: prfSalt.buffer
|
|
20149
|
+
}
|
|
20150
|
+
}
|
|
20151
|
+
}
|
|
20152
|
+
};
|
|
20153
|
+
const credential = await navigator.credentials.create({
|
|
20154
|
+
publicKey: publicKeyCredentialCreationOptions
|
|
20155
|
+
});
|
|
20156
|
+
if (!credential || !("response" in credential)) {
|
|
20157
|
+
throw new Error("Failed to create passkey credential");
|
|
20158
|
+
}
|
|
20159
|
+
const credentialId = Array.from(new Uint8Array(credential.rawId)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
20160
|
+
const extensionResults = credential.getClientExtensionResults();
|
|
20161
|
+
if (!extensionResults.prf?.results?.first) {
|
|
20162
|
+
throw new Error("PRF extension not supported or PRF output missing");
|
|
20163
|
+
}
|
|
20164
|
+
const prfOutputBuffer = extensionResults.prf.results.first;
|
|
20165
|
+
const prfOutput = new Uint8Array(prfOutputBuffer);
|
|
20166
|
+
const wrapKey = prfOutput;
|
|
20167
|
+
const keyStorageType = "passkey";
|
|
20168
|
+
const version5 = "v1";
|
|
20169
|
+
const aadBytes = new TextEncoder().encode(
|
|
20170
|
+
`volr/master-seed/v1|${userId}|${keyStorageType}|${version5}`
|
|
20171
|
+
);
|
|
20172
|
+
const encryptedBlob = await sdkCore.sealMasterSeed(masterSeed, wrapKey, aadBytes);
|
|
20173
|
+
const blob = new Blob(
|
|
20174
|
+
[
|
|
20175
|
+
encryptedBlob.cipher,
|
|
20176
|
+
encryptedBlob.nonce
|
|
20177
|
+
],
|
|
20178
|
+
{ type: "application/octet-stream" }
|
|
20179
|
+
);
|
|
20180
|
+
const accessToken = client.getAccessToken();
|
|
20181
|
+
if (!accessToken) {
|
|
20182
|
+
throw new Error("Access token is required");
|
|
20183
|
+
}
|
|
20184
|
+
const { key: blobUrl } = await sdkCore.uploadBlob({
|
|
20185
|
+
baseUrl,
|
|
20186
|
+
apiKey,
|
|
20187
|
+
accessToken,
|
|
20188
|
+
blob
|
|
20189
|
+
});
|
|
20190
|
+
if (!blobUrl) {
|
|
20191
|
+
throw new Error("Failed to upload blob");
|
|
20192
|
+
}
|
|
20193
|
+
const platform = detectPlatform3();
|
|
20194
|
+
await client.post("/wallet/migration/complete", {
|
|
20195
|
+
migrationToken,
|
|
20196
|
+
credentialId,
|
|
20197
|
+
blobUrl,
|
|
20198
|
+
prfInput: {
|
|
20199
|
+
projectId,
|
|
20200
|
+
credentialId
|
|
20201
|
+
},
|
|
20202
|
+
rpId,
|
|
20203
|
+
platform
|
|
20204
|
+
});
|
|
20205
|
+
return {
|
|
20206
|
+
credentialId,
|
|
20207
|
+
blobUrl,
|
|
20208
|
+
rpId
|
|
20209
|
+
};
|
|
20210
|
+
}
|
|
20211
|
+
async function getUserCredentials(client) {
|
|
20212
|
+
const response = await client.get("/wallet/credentials");
|
|
20213
|
+
return response.credentials;
|
|
20214
|
+
}
|
|
19974
20215
|
/*! Bundled license information:
|
|
19975
20216
|
|
|
19976
20217
|
@noble/hashes/esm/utils.js:
|
|
@@ -20026,6 +20267,7 @@ exports.checkPrfExtensionAvailable = checkPrfExtensionAvailable;
|
|
|
20026
20267
|
exports.checkPrfSupport = checkPrfSupport;
|
|
20027
20268
|
exports.compareERC20Balances = compareERC20Balances;
|
|
20028
20269
|
exports.compareWalletStates = compareWalletStates;
|
|
20270
|
+
exports.completeMigration = completeMigration;
|
|
20029
20271
|
exports.createGetNetworkInfo = createGetNetworkInfo;
|
|
20030
20272
|
exports.createPasskeyAdapter = createPasskeyAdapter;
|
|
20031
20273
|
exports.debugTransactionFailure = debugTransactionFailure;
|
|
@@ -20033,11 +20275,17 @@ exports.defaultIdempotencyKey = defaultIdempotencyKey;
|
|
|
20033
20275
|
exports.diagnoseTransactionFailure = diagnoseTransactionFailure;
|
|
20034
20276
|
exports.getERC20Balance = getERC20Balance;
|
|
20035
20277
|
exports.getPasskeyAuthGuidance = getPasskeyAuthGuidance;
|
|
20278
|
+
exports.getUserCredentials = getUserCredentials;
|
|
20036
20279
|
exports.getWalletState = getWalletState;
|
|
20037
20280
|
exports.isEIP7702Delegated = isEIP7702Delegated;
|
|
20038
20281
|
exports.isUserCancelledError = isUserCancelledError;
|
|
20282
|
+
exports.listenForSeedRequests = listenForSeedRequests;
|
|
20039
20283
|
exports.normalizeHex = normalizeHex;
|
|
20040
20284
|
exports.normalizeHexArray = normalizeHexArray;
|
|
20285
|
+
exports.openMigrationPopup = openMigrationPopup;
|
|
20286
|
+
exports.requestMigration = requestMigration;
|
|
20287
|
+
exports.requestSeedFromOpener = requestSeedFromOpener;
|
|
20288
|
+
exports.sendSeedToPopup = sendSeedToPopup;
|
|
20041
20289
|
exports.uploadBlobViaPresign = uploadBlobViaPresign;
|
|
20042
20290
|
exports.useDepositListener = useDepositListener;
|
|
20043
20291
|
exports.useInternalAuth = useInternalAuth;
|