@medialane/sdk 0.194.0 → 0.197.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/{chunk-BLEFV7GP.cjs → chunk-2R7XBA34.cjs} +82 -49
- package/dist/chunk-2R7XBA34.cjs.map +1 -0
- package/dist/{chunk-MOIM2AAQ.js → chunk-6WVUUBFI.js} +81 -50
- package/dist/chunk-6WVUUBFI.js.map +1 -0
- package/dist/{errors-C39AqEX6.d.cts → errors-CZm-NZK0.d.cts} +12 -6
- package/dist/{errors-Cc9W7FFi.d.ts → errors-h6H6cj3Q.d.ts} +12 -6
- package/dist/index.cjs +76 -72
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/starknet/index.cjs +75 -67
- package/dist/starknet/index.d.cts +2 -2
- package/dist/starknet/index.d.ts +2 -2
- package/dist/starknet/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-BLEFV7GP.cjs.map +0 -1
- package/dist/chunk-MOIM2AAQ.js.map +0 -1
|
@@ -1090,6 +1090,9 @@ async function deriveAesKey(prfSecret, hkdfInfo) {
|
|
|
1090
1090
|
["encrypt", "decrypt"]
|
|
1091
1091
|
);
|
|
1092
1092
|
}
|
|
1093
|
+
function generateDeviceKey() {
|
|
1094
|
+
return crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
1095
|
+
}
|
|
1093
1096
|
function generateStarkKeyPair() {
|
|
1094
1097
|
const privateKeyHex = "0x" + Array.from(ec.starkCurve.utils.randomPrivateKey()).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1095
1098
|
return { privateKeyHex, publicKeyHex: ec.starkCurve.getStarkKey(privateKeyHex) };
|
|
@@ -1212,6 +1215,38 @@ function computeAccountAddress(ownerPubkey, salt = 0) {
|
|
|
1212
1215
|
);
|
|
1213
1216
|
}
|
|
1214
1217
|
|
|
1218
|
+
// src/wallet/device-keys.ts
|
|
1219
|
+
var DATABASE = "medialane-wallet";
|
|
1220
|
+
var STORE = "device-keys";
|
|
1221
|
+
function open() {
|
|
1222
|
+
return new Promise((resolve, reject) => {
|
|
1223
|
+
const request = indexedDB.open(DATABASE, 1);
|
|
1224
|
+
request.onupgradeneeded = () => request.result.createObjectStore(STORE);
|
|
1225
|
+
request.onsuccess = () => resolve(request.result);
|
|
1226
|
+
request.onerror = () => reject(request.error);
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
async function run(mode, act) {
|
|
1230
|
+
const db = await open();
|
|
1231
|
+
try {
|
|
1232
|
+
return await new Promise((resolve, reject) => {
|
|
1233
|
+
const request = act(db.transaction(STORE, mode).objectStore(STORE));
|
|
1234
|
+
request.onsuccess = () => resolve(request.result);
|
|
1235
|
+
request.onerror = () => reject(request.error);
|
|
1236
|
+
});
|
|
1237
|
+
} finally {
|
|
1238
|
+
db.close();
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
var indexedDbDeviceKeys = {
|
|
1242
|
+
async save(credentialId, key) {
|
|
1243
|
+
await run("readwrite", (store) => store.put(key, credentialId));
|
|
1244
|
+
},
|
|
1245
|
+
async load(credentialId) {
|
|
1246
|
+
return await run("readonly", (store) => store.get(credentialId)) ?? null;
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
|
|
1215
1250
|
// src/wallet/passkey.ts
|
|
1216
1251
|
var PasskeyCancelledError = class extends Error {
|
|
1217
1252
|
constructor(message = "Passkey prompt was cancelled.") {
|
|
@@ -1219,6 +1254,12 @@ var PasskeyCancelledError = class extends Error {
|
|
|
1219
1254
|
this.name = "PasskeyCancelledError";
|
|
1220
1255
|
}
|
|
1221
1256
|
};
|
|
1257
|
+
var DeviceKeyMissingError = class extends Error {
|
|
1258
|
+
constructor() {
|
|
1259
|
+
super("This browser no longer holds the wallet key. Recover the wallet with its recovery key.");
|
|
1260
|
+
this.name = "DeviceKeyMissingError";
|
|
1261
|
+
}
|
|
1262
|
+
};
|
|
1222
1263
|
var PasskeyUnsupportedError = class extends Error {
|
|
1223
1264
|
constructor(reason) {
|
|
1224
1265
|
super(
|
|
@@ -1251,21 +1292,7 @@ function createPasskeyOwner(config) {
|
|
|
1251
1292
|
if (!api) throw new PasskeyUnsupportedError("no-webauthn");
|
|
1252
1293
|
return api;
|
|
1253
1294
|
};
|
|
1254
|
-
const browserRefusesPrf = async () => {
|
|
1255
|
-
const read = config.clientCapabilities ?? (typeof PublicKeyCredential !== "undefined" && typeof PublicKeyCredential.getClientCapabilities === "function" ? () => PublicKeyCredential.getClientCapabilities() : void 0);
|
|
1256
|
-
if (!read) return false;
|
|
1257
|
-
try {
|
|
1258
|
-
return (await read())["extension:prf"] === false;
|
|
1259
|
-
} catch {
|
|
1260
|
-
return false;
|
|
1261
|
-
}
|
|
1262
|
-
};
|
|
1263
|
-
const ensurePrfPossible = async () => {
|
|
1264
|
-
credentialsApi();
|
|
1265
|
-
if (await browserRefusesPrf()) throw new PasskeyUnsupportedError("no-prf");
|
|
1266
|
-
};
|
|
1267
1295
|
async function registerPasskey() {
|
|
1268
|
-
await ensurePrfPossible();
|
|
1269
1296
|
let credential;
|
|
1270
1297
|
try {
|
|
1271
1298
|
credential = await credentialsApi().create({
|
|
@@ -1279,6 +1306,7 @@ function createPasskeyOwner(config) {
|
|
|
1279
1306
|
{ type: "public-key", alg: -257 }
|
|
1280
1307
|
],
|
|
1281
1308
|
authenticatorSelection: {
|
|
1309
|
+
authenticatorAttachment: "platform",
|
|
1282
1310
|
residentKey: "required",
|
|
1283
1311
|
userVerification: "required"
|
|
1284
1312
|
},
|
|
@@ -1292,53 +1320,55 @@ function createPasskeyOwner(config) {
|
|
|
1292
1320
|
const prf = credential.getClientExtensionResults().prf;
|
|
1293
1321
|
return {
|
|
1294
1322
|
credentialId: encodeBase64(credential.rawId),
|
|
1295
|
-
prfFirst: prf?.results?.first ?? null
|
|
1296
|
-
prfEnabled: prf?.enabled
|
|
1323
|
+
prfFirst: prf?.results?.first ?? null
|
|
1297
1324
|
};
|
|
1298
1325
|
}
|
|
1299
|
-
async function
|
|
1300
|
-
await ensurePrfPossible();
|
|
1301
|
-
let assertion;
|
|
1326
|
+
async function assertPasskey(credentialId, extensions) {
|
|
1302
1327
|
try {
|
|
1303
|
-
|
|
1328
|
+
return await credentialsApi().get({
|
|
1304
1329
|
publicKey: {
|
|
1305
1330
|
challenge: randomBytes(32),
|
|
1306
1331
|
rpId: config.relyingPartyId(),
|
|
1307
1332
|
allowCredentials: [{ type: "public-key", id: decodeBase64(credentialId) }],
|
|
1308
1333
|
userVerification: "required",
|
|
1309
|
-
extensions
|
|
1334
|
+
...extensions ? { extensions } : {}
|
|
1310
1335
|
}
|
|
1311
1336
|
});
|
|
1312
1337
|
} catch (err) {
|
|
1313
1338
|
if (isPasskeyCancellation(err)) throw new PasskeyCancelledError();
|
|
1314
1339
|
throw err;
|
|
1315
1340
|
}
|
|
1341
|
+
}
|
|
1342
|
+
async function prfSecret(credentialId) {
|
|
1343
|
+
const assertion = await assertPasskey(credentialId, {
|
|
1344
|
+
prf: { eval: { first: config.prfSalt } }
|
|
1345
|
+
});
|
|
1316
1346
|
const result = assertion.getClientExtensionResults().prf?.results?.first;
|
|
1317
1347
|
if (!result) throw new PasskeyUnsupportedError("no-prf");
|
|
1318
1348
|
return new Uint8Array(result);
|
|
1319
1349
|
}
|
|
1320
|
-
const
|
|
1321
|
-
|
|
1322
|
-
if (
|
|
1323
|
-
|
|
1324
|
-
try {
|
|
1325
|
-
await signal({ rpId: config.relyingPartyId(), credentialId: base64url });
|
|
1326
|
-
} catch {
|
|
1327
|
-
return;
|
|
1350
|
+
const deviceKeys = config.deviceKeys ?? indexedDbDeviceKeys;
|
|
1351
|
+
async function lockFor(registration) {
|
|
1352
|
+
if (registration.prfFirst) {
|
|
1353
|
+
return { aes: await deriveAesKey(new Uint8Array(registration.prfFirst), config.hkdfInfo) };
|
|
1328
1354
|
}
|
|
1329
|
-
};
|
|
1330
|
-
async function secretFromRegistration(registration) {
|
|
1331
|
-
if (registration.prfFirst) return new Uint8Array(registration.prfFirst);
|
|
1332
1355
|
try {
|
|
1333
|
-
|
|
1334
|
-
return await prfSecret(registration.credentialId);
|
|
1356
|
+
return { aes: await deriveAesKey(await prfSecret(registration.credentialId), config.hkdfInfo) };
|
|
1335
1357
|
} catch (err) {
|
|
1336
|
-
if (err instanceof PasskeyUnsupportedError)
|
|
1337
|
-
throw err;
|
|
1358
|
+
if (!(err instanceof PasskeyUnsupportedError) || err.reason !== "no-prf") throw err;
|
|
1338
1359
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1360
|
+
const aes = await generateDeviceKey();
|
|
1361
|
+
await deviceKeys.save(registration.credentialId, aes);
|
|
1362
|
+
return { aes, lock: "device" };
|
|
1363
|
+
}
|
|
1364
|
+
async function unlockFor(sealed) {
|
|
1365
|
+
if (sealed.lock !== "device") return deriveAesKey(await prfSecret(sealed.credentialId), config.hkdfInfo);
|
|
1366
|
+
await assertPasskey(sealed.credentialId);
|
|
1367
|
+
const aes = await deviceKeys.load(sealed.credentialId);
|
|
1368
|
+
if (!aes) throw new DeviceKeyMissingError();
|
|
1369
|
+
return aes;
|
|
1370
|
+
}
|
|
1371
|
+
async function seal(aes, privateKeyHex) {
|
|
1342
1372
|
const iv = randomBytes(12);
|
|
1343
1373
|
const ciphertext = await sealPrivateKey(aes, iv, privateKeyHex);
|
|
1344
1374
|
return { iv: encodeBase64(iv), ciphertext: encodeBase64(ciphertext) };
|
|
@@ -1346,36 +1376,37 @@ function createPasskeyOwner(config) {
|
|
|
1346
1376
|
return {
|
|
1347
1377
|
async createOwnerKey() {
|
|
1348
1378
|
const registration = await registerPasskey();
|
|
1349
|
-
const
|
|
1379
|
+
const { aes, lock } = await lockFor(registration);
|
|
1350
1380
|
const { privateKeyHex, publicKeyHex } = generateStarkKeyPair();
|
|
1351
|
-
const { iv, ciphertext } = await seal(
|
|
1381
|
+
const { iv, ciphertext } = await seal(aes, privateKeyHex);
|
|
1352
1382
|
return {
|
|
1353
1383
|
sealed: {
|
|
1354
1384
|
credentialId: registration.credentialId,
|
|
1355
1385
|
ownerPubKey: publicKeyHex,
|
|
1356
1386
|
address: computeAccountAddress(publicKeyHex, 0),
|
|
1357
1387
|
iv,
|
|
1358
|
-
ciphertext
|
|
1388
|
+
ciphertext,
|
|
1389
|
+
...lock ? { lock } : {}
|
|
1359
1390
|
},
|
|
1360
1391
|
privateKeyHex
|
|
1361
1392
|
};
|
|
1362
1393
|
},
|
|
1363
1394
|
async unlockOwnerKey(sealed) {
|
|
1364
|
-
const
|
|
1365
|
-
const aes = await deriveAesKey(secret, config.hkdfInfo);
|
|
1395
|
+
const aes = await unlockFor(sealed);
|
|
1366
1396
|
return unsealPrivateKey(aes, decodeBase64(sealed.iv), decodeBase64(sealed.ciphertext));
|
|
1367
1397
|
},
|
|
1368
1398
|
async sealImportedOwnerKey(recovery) {
|
|
1369
1399
|
const { privateKeyHex, publicKeyHex } = starkKeyPairFromPrivateKey(recovery.privateKey);
|
|
1370
1400
|
const registration = await registerPasskey();
|
|
1371
|
-
const
|
|
1372
|
-
const { iv, ciphertext } = await seal(
|
|
1401
|
+
const { aes, lock } = await lockFor(registration);
|
|
1402
|
+
const { iv, ciphertext } = await seal(aes, privateKeyHex);
|
|
1373
1403
|
return {
|
|
1374
1404
|
credentialId: registration.credentialId,
|
|
1375
1405
|
ownerPubKey: publicKeyHex,
|
|
1376
1406
|
address: recovery.walletAddress,
|
|
1377
1407
|
iv,
|
|
1378
|
-
ciphertext
|
|
1408
|
+
ciphertext,
|
|
1409
|
+
...lock ? { lock } : {}
|
|
1379
1410
|
};
|
|
1380
1411
|
}
|
|
1381
1412
|
};
|
|
@@ -1817,6 +1848,6 @@ var UserFacingError = class extends Error {
|
|
|
1817
1848
|
}
|
|
1818
1849
|
};
|
|
1819
1850
|
|
|
1820
|
-
export { ApiClient, DEFAULT_CURRENCY, FeeConfigSchema, InvalidStarkPrivateKeyError, MedialaneApiError, PasskeyCancelledError, PasskeyUnsupportedError, STARKNET_COLLECTION_1155_CLASS_HASH, STARKNET_COLLECTION_1155_CONTRACT, STARKNET_COLLECTION_1155_FACTORY_CLASS_HASH, STARKNET_COLLECTION_1155_START_BLOCK, STARKNET_COLLECTION_721_CONTRACT, STARKNET_COLLECTION_721_START_BLOCK, STARKNET_CREATOR_COIN_CLASS_HASH, STARKNET_CREATOR_COIN_EKUBO_LAUNCHER, STARKNET_CREATOR_COIN_FACTORY_CLASS_HASH, STARKNET_CREATOR_COIN_FACTORY_CONTRACT, STARKNET_CREATOR_COIN_START_BLOCK, STARKNET_DATA_TOKENIZATION_721_CONTRACT, STARKNET_DROP_COLLECTION_CLASS_HASH, STARKNET_DROP_FACTORY_CONTRACT, STARKNET_DROP_FACTORY_START_BLOCK, STARKNET_EKUBO_CORE, STARKNET_GENESIS_MINT_CONTRACT, STARKNET_GENESIS_NFT_URI, STARKNET_IPCOLLECTION_CLASS_HASH, STARKNET_IPNFT_CLASS_HASH, STARKNET_IP_CLUB_COLLECTION_CLASS_HASH, STARKNET_IP_CLUB_FACTORY_CONTRACT, STARKNET_IP_SPONSORSHIP_CLASS_HASH, STARKNET_IP_SPONSORSHIP_CONTRACT, STARKNET_IP_TICKETS_FACTORY_CONTRACT, STARKNET_IP_TICKET_COLLECTION_CLASS_HASH, STARKNET_MARKETPLACE_1155_CLASS_HASH, STARKNET_MARKETPLACE_1155_CONTRACT, STARKNET_MARKETPLACE_1155_START_BLOCK, STARKNET_MARKETPLACE_721_CLASS_HASH, STARKNET_MARKETPLACE_721_CONTRACT, STARKNET_MARKETPLACE_721_START_BLOCK, STARKNET_MEDIAWALLET_CLASS_HASH, STARKNET_NFTCOMMENTS_CONTRACT, STARKNET_POP_COLLECTION_CLASS_HASH, STARKNET_POP_FACTORY_CONTRACT, STARKNET_POP_FACTORY_START_BLOCK, SUPPORTED_TOKENS, SUPPORTED_URL_CHAINS, UserFacingError, assetHref, chainFromSlug, chainSlug, coinHref, collectionHref, computeAccountAddress, createPasskeyOwner, deriveAesKey, dropHref, encodeU256, formatAmount, generateStarkKeyPair, getListableTokens, getService, getServicesByCapability, getTokenByAddress, getTokenBySymbol, hasCapability, isServiceId, listServices, normalizeAddress, normalizeHash, ownerConstructorCalldata, parseAmount, profileHref, resolveAppFeeConfig, resolveConfig, resolveFeeConfig, sealPrivateKey, shortenAddress, signWithPrivateKey, starkKeyPairFromPrivateKey, stringifyBigInts, u256ToBigInt, unsealPrivateKey };
|
|
1821
|
-
//# sourceMappingURL=chunk-
|
|
1822
|
-
//# sourceMappingURL=chunk-
|
|
1851
|
+
export { ApiClient, DEFAULT_CURRENCY, DeviceKeyMissingError, FeeConfigSchema, InvalidStarkPrivateKeyError, MedialaneApiError, PasskeyCancelledError, PasskeyUnsupportedError, STARKNET_COLLECTION_1155_CLASS_HASH, STARKNET_COLLECTION_1155_CONTRACT, STARKNET_COLLECTION_1155_FACTORY_CLASS_HASH, STARKNET_COLLECTION_1155_START_BLOCK, STARKNET_COLLECTION_721_CONTRACT, STARKNET_COLLECTION_721_START_BLOCK, STARKNET_CREATOR_COIN_CLASS_HASH, STARKNET_CREATOR_COIN_EKUBO_LAUNCHER, STARKNET_CREATOR_COIN_FACTORY_CLASS_HASH, STARKNET_CREATOR_COIN_FACTORY_CONTRACT, STARKNET_CREATOR_COIN_START_BLOCK, STARKNET_DATA_TOKENIZATION_721_CONTRACT, STARKNET_DROP_COLLECTION_CLASS_HASH, STARKNET_DROP_FACTORY_CONTRACT, STARKNET_DROP_FACTORY_START_BLOCK, STARKNET_EKUBO_CORE, STARKNET_GENESIS_MINT_CONTRACT, STARKNET_GENESIS_NFT_URI, STARKNET_IPCOLLECTION_CLASS_HASH, STARKNET_IPNFT_CLASS_HASH, STARKNET_IP_CLUB_COLLECTION_CLASS_HASH, STARKNET_IP_CLUB_FACTORY_CONTRACT, STARKNET_IP_SPONSORSHIP_CLASS_HASH, STARKNET_IP_SPONSORSHIP_CONTRACT, STARKNET_IP_TICKETS_FACTORY_CONTRACT, STARKNET_IP_TICKET_COLLECTION_CLASS_HASH, STARKNET_MARKETPLACE_1155_CLASS_HASH, STARKNET_MARKETPLACE_1155_CONTRACT, STARKNET_MARKETPLACE_1155_START_BLOCK, STARKNET_MARKETPLACE_721_CLASS_HASH, STARKNET_MARKETPLACE_721_CONTRACT, STARKNET_MARKETPLACE_721_START_BLOCK, STARKNET_MEDIAWALLET_CLASS_HASH, STARKNET_NFTCOMMENTS_CONTRACT, STARKNET_POP_COLLECTION_CLASS_HASH, STARKNET_POP_FACTORY_CONTRACT, STARKNET_POP_FACTORY_START_BLOCK, SUPPORTED_TOKENS, SUPPORTED_URL_CHAINS, UserFacingError, assetHref, chainFromSlug, chainSlug, coinHref, collectionHref, computeAccountAddress, createPasskeyOwner, deriveAesKey, dropHref, encodeU256, formatAmount, generateStarkKeyPair, getListableTokens, getService, getServicesByCapability, getTokenByAddress, getTokenBySymbol, hasCapability, indexedDbDeviceKeys, isServiceId, listServices, normalizeAddress, normalizeHash, ownerConstructorCalldata, parseAmount, profileHref, resolveAppFeeConfig, resolveConfig, resolveFeeConfig, sealPrivateKey, shortenAddress, signWithPrivateKey, starkKeyPairFromPrivateKey, stringifyBigInts, u256ToBigInt, unsealPrivateKey };
|
|
1852
|
+
//# sourceMappingURL=chunk-6WVUUBFI.js.map
|
|
1853
|
+
//# sourceMappingURL=chunk-6WVUUBFI.js.map
|