@weblock-wallet/sdk 0.1.70 → 0.1.71
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 +256 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +256 -84
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -104156,8 +104156,14 @@ var STORAGE_KEYS = {
|
|
|
104156
104156
|
walletAddress: (orgHost) => `${orgHost}:walletAddress`,
|
|
104157
104157
|
share2: (orgHost) => `${orgHost}:share2`,
|
|
104158
104158
|
encryptedShare2: (orgHost) => `${orgHost}:encryptedShare2`,
|
|
104159
|
-
|
|
104160
|
-
|
|
104159
|
+
// User-scoped keys to prevent cross-account mixing on the same device.
|
|
104160
|
+
deviceId: (orgHost, firebaseId) => `${orgHost}:${firebaseId}:deviceId`,
|
|
104161
|
+
encryptedShare2Device: (orgHost, firebaseId) => `${orgHost}:${firebaseId}:encryptedShare2_device`,
|
|
104162
|
+
deviceSecret: (orgHost, firebaseId) => `${orgHost}:${firebaseId}:deviceSecret`,
|
|
104163
|
+
// Legacy keys (kept for migration / cleanup)
|
|
104164
|
+
encryptedShare2DeviceLegacy: (orgHost) => `${orgHost}:encryptedShare2_device`,
|
|
104165
|
+
deviceSecretLegacy: (orgHost) => `${orgHost}:deviceSecret`,
|
|
104166
|
+
deviceIdLegacy: (orgHost) => `${orgHost}:deviceId`,
|
|
104161
104167
|
firebaseId: (orgHost) => `${orgHost}:firebaseId`,
|
|
104162
104168
|
accessToken: (orgHost) => `${orgHost}:accessToken`,
|
|
104163
104169
|
isNewUser: (orgHost) => `${orgHost}:isNewUser`
|
|
@@ -104189,28 +104195,76 @@ var WalletService = class {
|
|
|
104189
104195
|
isSixDigitPin(pin) {
|
|
104190
104196
|
return /^[0-9]{6}$/.test(pin);
|
|
104191
104197
|
}
|
|
104198
|
+
normalizeAddr(v5) {
|
|
104199
|
+
const s5 = String(v5 ?? "").trim();
|
|
104200
|
+
return s5 ? s5.toLowerCase() : "";
|
|
104201
|
+
}
|
|
104202
|
+
addressesMismatch(a5, b4) {
|
|
104203
|
+
return !!a5 && !!b4 && a5.toLowerCase() !== b4.toLowerCase();
|
|
104204
|
+
}
|
|
104205
|
+
/**
|
|
104206
|
+
* deviceId: stable identifier for the current device/browser profile.
|
|
104207
|
+
* Used to store/fetch server-side device recovery backup.
|
|
104208
|
+
*/
|
|
104209
|
+
async getOrCreateDeviceId(firebaseId) {
|
|
104210
|
+
const scopedKey = STORAGE_KEYS.deviceId(this.orgHost, firebaseId);
|
|
104211
|
+
const existing = await LocalForage.get(scopedKey);
|
|
104212
|
+
if (existing) return existing;
|
|
104213
|
+
const legacy = await LocalForage.get(
|
|
104214
|
+
STORAGE_KEYS.deviceIdLegacy(this.orgHost)
|
|
104215
|
+
);
|
|
104216
|
+
if (legacy) {
|
|
104217
|
+
await LocalForage.save(scopedKey, legacy);
|
|
104218
|
+
return legacy;
|
|
104219
|
+
}
|
|
104220
|
+
const id = randomBytes(16).toString("hex");
|
|
104221
|
+
await LocalForage.save(scopedKey, id);
|
|
104222
|
+
return id;
|
|
104223
|
+
}
|
|
104192
104224
|
/**
|
|
104193
|
-
* deviceSecret:
|
|
104194
|
-
*
|
|
104225
|
+
* deviceSecret: device recovery secret. In the original SDK this was local-only.
|
|
104226
|
+
* To enable PIN reset after local storage wipe, we back it up to the server
|
|
104227
|
+
* (server should encrypt-at-rest; transport is TLS).
|
|
104195
104228
|
*/
|
|
104196
|
-
async getOrCreateDeviceSecret() {
|
|
104197
|
-
const
|
|
104198
|
-
const existing = await LocalForage.get(
|
|
104229
|
+
async getOrCreateDeviceSecret(firebaseId) {
|
|
104230
|
+
const scopedKey = STORAGE_KEYS.deviceSecret(this.orgHost, firebaseId);
|
|
104231
|
+
const existing = await LocalForage.get(scopedKey);
|
|
104199
104232
|
if (existing) return existing;
|
|
104233
|
+
const legacy = await LocalForage.get(
|
|
104234
|
+
STORAGE_KEYS.deviceSecretLegacy(this.orgHost)
|
|
104235
|
+
);
|
|
104236
|
+
if (legacy) {
|
|
104237
|
+
await LocalForage.save(scopedKey, legacy);
|
|
104238
|
+
return legacy;
|
|
104239
|
+
}
|
|
104200
104240
|
const secret = randomBytes(32).toString("hex");
|
|
104201
|
-
await LocalForage.save(
|
|
104241
|
+
await LocalForage.save(scopedKey, secret);
|
|
104202
104242
|
return secret;
|
|
104203
104243
|
}
|
|
104204
104244
|
/**
|
|
104205
|
-
* PATCH APPLIED:
|
|
104206
104245
|
* Always overwrite encryptedShare2_device when we have a fresh share2.
|
|
104207
|
-
*
|
|
104246
|
+
* Also upsert to server so that PIN reset can work after local storage wipe.
|
|
104247
|
+
*
|
|
104248
|
+
* Note: Server backup is best-effort; we do not fail the main flow if backup fails.
|
|
104208
104249
|
*/
|
|
104209
104250
|
async ensureDeviceEncryptedShare2(share2Plain, firebaseId) {
|
|
104210
|
-
const
|
|
104211
|
-
const deviceSecret = await this.getOrCreateDeviceSecret();
|
|
104251
|
+
const deviceId = await this.getOrCreateDeviceId(firebaseId);
|
|
104252
|
+
const deviceSecret = await this.getOrCreateDeviceSecret(firebaseId);
|
|
104253
|
+
const encryptedKey = STORAGE_KEYS.encryptedShare2Device(
|
|
104254
|
+
this.orgHost,
|
|
104255
|
+
firebaseId
|
|
104256
|
+
);
|
|
104212
104257
|
const encrypted = Crypto.encryptShare(share2Plain, deviceSecret, firebaseId);
|
|
104213
104258
|
await LocalForage.save(encryptedKey, encrypted);
|
|
104259
|
+
try {
|
|
104260
|
+
await this.walletClient.upsertDeviceRecovery({
|
|
104261
|
+
deviceId,
|
|
104262
|
+
encryptedShare2Device: encrypted,
|
|
104263
|
+
deviceSecret
|
|
104264
|
+
});
|
|
104265
|
+
} catch (e7) {
|
|
104266
|
+
console.warn("[WalletService] device recovery backup upsert failed", e7);
|
|
104267
|
+
}
|
|
104214
104268
|
}
|
|
104215
104269
|
async getAddress() {
|
|
104216
104270
|
try {
|
|
@@ -104299,69 +104353,106 @@ var WalletService = class {
|
|
|
104299
104353
|
);
|
|
104300
104354
|
}
|
|
104301
104355
|
}
|
|
104302
|
-
// client/src/core/services/wallet.ts
|
|
104303
|
-
// Full version of retrieveWallet() with the address-mismatch guard added.
|
|
104304
|
-
// Assumes existing imports/types in this file:
|
|
104305
|
-
// - SDKError, SDKErrorCode
|
|
104306
|
-
// - LocalForage
|
|
104307
|
-
// - STORAGE_KEYS
|
|
104308
|
-
// - Crypto (encryptShare/decryptShare)
|
|
104309
|
-
// - Secrets (combine)
|
|
104310
|
-
// - Wallet (ethers Wallet or equivalent)
|
|
104311
|
-
// - this.walletClient.getWallet()
|
|
104312
|
-
// - this.orgHost, this.walletAddress
|
|
104313
|
-
// - this.isSixDigitPin(password)
|
|
104314
104356
|
async retrieveWallet(password) {
|
|
104315
104357
|
try {
|
|
104358
|
+
const accessToken = await LocalForage.get(
|
|
104359
|
+
STORAGE_KEYS.accessToken(this.orgHost)
|
|
104360
|
+
);
|
|
104361
|
+
if (!accessToken) {
|
|
104362
|
+
throw new SDKError("Access token not found", "AUTH_REQUIRED" /* AUTH_REQUIRED */);
|
|
104363
|
+
}
|
|
104316
104364
|
const firebaseId = await LocalForage.get(
|
|
104317
104365
|
STORAGE_KEYS.firebaseId(this.orgHost)
|
|
104318
104366
|
);
|
|
104319
104367
|
if (!firebaseId) {
|
|
104320
104368
|
throw new SDKError("Not logged in", "AUTH_REQUIRED" /* AUTH_REQUIRED */);
|
|
104321
104369
|
}
|
|
104322
|
-
if (!
|
|
104370
|
+
if (!this.isSixDigitPin(password)) {
|
|
104323
104371
|
throw new SDKError(
|
|
104324
104372
|
"PIN must be a 6-digit number",
|
|
104325
104373
|
"INVALID_PARAMS" /* INVALID_PARAMS */
|
|
104326
104374
|
);
|
|
104327
104375
|
}
|
|
104376
|
+
const decryptShareOrThrow = (encryptedShare) => {
|
|
104377
|
+
try {
|
|
104378
|
+
return Crypto.decryptShare(encryptedShare, password, firebaseId);
|
|
104379
|
+
} catch (e7) {
|
|
104380
|
+
if (this.isInvalidPasswordError(e7)) {
|
|
104381
|
+
throw new SDKError(
|
|
104382
|
+
"Incorrect PIN code",
|
|
104383
|
+
"INVALID_PASSWORD" /* INVALID_PASSWORD */,
|
|
104384
|
+
e7
|
|
104385
|
+
);
|
|
104386
|
+
}
|
|
104387
|
+
throw e7;
|
|
104388
|
+
}
|
|
104389
|
+
};
|
|
104328
104390
|
const walletInfo = await this.walletClient.getWallet();
|
|
104329
|
-
const
|
|
104330
|
-
|
|
104331
|
-
|
|
104332
|
-
throw new SDKError(
|
|
104333
|
-
"Wallet is not initialized on the server",
|
|
104334
|
-
"WALLET_NOT_FOUND" /* WALLET_NOT_FOUND */
|
|
104335
|
-
);
|
|
104336
|
-
}
|
|
104337
|
-
const encryptedShare2 = await LocalForage.get(
|
|
104338
|
-
STORAGE_KEYS.encryptedShare2(this.orgHost)
|
|
104391
|
+
const serverAddr = this.normalizeAddr(walletInfo?.address);
|
|
104392
|
+
let share2 = await LocalForage.get(
|
|
104393
|
+
STORAGE_KEYS.share2(this.orgHost)
|
|
104339
104394
|
);
|
|
104340
|
-
if (!
|
|
104341
|
-
|
|
104342
|
-
|
|
104343
|
-
"RECOVERY_NOT_AVAILABLE" /* RECOVERY_NOT_AVAILABLE */
|
|
104344
|
-
);
|
|
104345
|
-
}
|
|
104346
|
-
let share2;
|
|
104347
|
-
try {
|
|
104348
|
-
share2 = Crypto.decryptShare(encryptedShare2, password, firebaseId);
|
|
104349
|
-
} catch (e7) {
|
|
104350
|
-
throw new SDKError(
|
|
104351
|
-
"Invalid PIN or corrupted local recovery material",
|
|
104352
|
-
"INVALID_PIN" /* INVALID_PIN */,
|
|
104353
|
-
e7
|
|
104395
|
+
if (!share2) {
|
|
104396
|
+
const encryptedShare2 = await LocalForage.get(
|
|
104397
|
+
STORAGE_KEYS.encryptedShare2(this.orgHost)
|
|
104354
104398
|
);
|
|
104399
|
+
if (encryptedShare2) {
|
|
104400
|
+
share2 = decryptShareOrThrow(encryptedShare2);
|
|
104401
|
+
await LocalForage.save(STORAGE_KEYS.share2(this.orgHost), share2);
|
|
104402
|
+
} else {
|
|
104403
|
+
const share3 = decryptShareOrThrow(
|
|
104404
|
+
walletInfo.encryptedShare3
|
|
104405
|
+
);
|
|
104406
|
+
const privateKey2 = await Secrets.combine([
|
|
104407
|
+
walletInfo.share1,
|
|
104408
|
+
share3
|
|
104409
|
+
]);
|
|
104410
|
+
const wallet2 = new import_ethers2.Wallet(privateKey2);
|
|
104411
|
+
const derivedAddr2 = this.normalizeAddr(wallet2.address);
|
|
104412
|
+
if (this.addressesMismatch(serverAddr, derivedAddr2)) {
|
|
104413
|
+
throw new SDKError(
|
|
104414
|
+
`Recovered wallet address mismatch. server=${serverAddr} derived=${derivedAddr2}`,
|
|
104415
|
+
"WALLET_RECOVERY_FAILED" /* WALLET_RECOVERY_FAILED */
|
|
104416
|
+
);
|
|
104417
|
+
}
|
|
104418
|
+
const newShares = await Secrets.split(wallet2.privateKey, 3, 2);
|
|
104419
|
+
const [newShare1, newShare2, newShare3] = newShares;
|
|
104420
|
+
await this.walletClient.updateWalletKey({
|
|
104421
|
+
share1: newShare1,
|
|
104422
|
+
encryptedShare3: Crypto.encryptShare(
|
|
104423
|
+
newShare3,
|
|
104424
|
+
password,
|
|
104425
|
+
firebaseId
|
|
104426
|
+
)
|
|
104427
|
+
});
|
|
104428
|
+
await LocalForage.save(STORAGE_KEYS.share2(this.orgHost), newShare2);
|
|
104429
|
+
await LocalForage.save(
|
|
104430
|
+
STORAGE_KEYS.encryptedShare2(this.orgHost),
|
|
104431
|
+
Crypto.encryptShare(newShare2, password, firebaseId)
|
|
104432
|
+
);
|
|
104433
|
+
await this.ensureDeviceEncryptedShare2(newShare2, firebaseId);
|
|
104434
|
+
this.walletAddress = wallet2.address;
|
|
104435
|
+
await LocalForage.save(
|
|
104436
|
+
STORAGE_KEYS.walletAddress(this.orgHost),
|
|
104437
|
+
wallet2.address
|
|
104438
|
+
);
|
|
104439
|
+
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104440
|
+
return wallet2.address;
|
|
104441
|
+
}
|
|
104355
104442
|
}
|
|
104356
|
-
const privateKey = await Secrets.combine([
|
|
104443
|
+
const privateKey = await Secrets.combine([
|
|
104444
|
+
walletInfo.share1,
|
|
104445
|
+
share2
|
|
104446
|
+
]);
|
|
104357
104447
|
const wallet = new import_ethers2.Wallet(privateKey);
|
|
104358
|
-
const derivedAddr = wallet.address
|
|
104359
|
-
if (serverAddr
|
|
104448
|
+
const derivedAddr = this.normalizeAddr(wallet.address);
|
|
104449
|
+
if (this.addressesMismatch(serverAddr, derivedAddr)) {
|
|
104360
104450
|
throw new SDKError(
|
|
104361
104451
|
`Recovered wallet address mismatch. server=${serverAddr} derived=${derivedAddr}`,
|
|
104362
104452
|
"WALLET_RECOVERY_FAILED" /* WALLET_RECOVERY_FAILED */
|
|
104363
104453
|
);
|
|
104364
104454
|
}
|
|
104455
|
+
await this.ensureDeviceEncryptedShare2(share2, firebaseId);
|
|
104365
104456
|
this.walletAddress = wallet.address;
|
|
104366
104457
|
await LocalForage.save(
|
|
104367
104458
|
STORAGE_KEYS.walletAddress(this.orgHost),
|
|
@@ -104370,6 +104461,8 @@ var WalletService = class {
|
|
|
104370
104461
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104371
104462
|
return wallet.address;
|
|
104372
104463
|
} catch (error) {
|
|
104464
|
+
this.walletAddress = null;
|
|
104465
|
+
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104373
104466
|
if (error instanceof SDKError) throw error;
|
|
104374
104467
|
throw new SDKError(
|
|
104375
104468
|
"Failed to retrieve wallet",
|
|
@@ -104379,7 +104472,8 @@ var WalletService = class {
|
|
|
104379
104472
|
}
|
|
104380
104473
|
}
|
|
104381
104474
|
/**
|
|
104382
|
-
* PIN reset (same private key/address) using
|
|
104475
|
+
* PIN reset (same private key/address) using device recovery material.
|
|
104476
|
+
* If local recovery material is missing, it attempts to restore it from server backup.
|
|
104383
104477
|
*/
|
|
104384
104478
|
async resetPin(newPassword) {
|
|
104385
104479
|
try {
|
|
@@ -104401,42 +104495,71 @@ var WalletService = class {
|
|
|
104401
104495
|
"INVALID_PARAMS" /* INVALID_PARAMS */
|
|
104402
104496
|
);
|
|
104403
104497
|
}
|
|
104404
|
-
|
|
104405
|
-
STORAGE_KEYS.encryptedShare2Device(this.orgHost)
|
|
104498
|
+
let encryptedDevice = await LocalForage.get(
|
|
104499
|
+
STORAGE_KEYS.encryptedShare2Device(this.orgHost, firebaseId)
|
|
104406
104500
|
);
|
|
104407
|
-
|
|
104408
|
-
STORAGE_KEYS.deviceSecret(this.orgHost)
|
|
104501
|
+
let deviceSecret = await LocalForage.get(
|
|
104502
|
+
STORAGE_KEYS.deviceSecret(this.orgHost, firebaseId)
|
|
104409
104503
|
);
|
|
104410
104504
|
if (!encryptedDevice || !deviceSecret) {
|
|
104411
|
-
|
|
104412
|
-
|
|
104413
|
-
|
|
104505
|
+
let backup;
|
|
104506
|
+
try {
|
|
104507
|
+
backup = await this.walletClient.getDeviceRecovery(void 0);
|
|
104508
|
+
} catch (e7) {
|
|
104509
|
+
throw new SDKError(
|
|
104510
|
+
"PIN reset is not available on this device",
|
|
104511
|
+
"RECOVERY_NOT_AVAILABLE" /* RECOVERY_NOT_AVAILABLE */,
|
|
104512
|
+
e7
|
|
104513
|
+
);
|
|
104514
|
+
}
|
|
104515
|
+
if (!backup?.found || !backup?.encryptedShare2Device || !backup?.deviceSecret) {
|
|
104516
|
+
throw new SDKError(
|
|
104517
|
+
"PIN reset is not available. No device recovery backup found for this user.",
|
|
104518
|
+
"RECOVERY_NOT_AVAILABLE" /* RECOVERY_NOT_AVAILABLE */
|
|
104519
|
+
);
|
|
104520
|
+
}
|
|
104521
|
+
encryptedDevice = backup.encryptedShare2Device;
|
|
104522
|
+
deviceSecret = backup.deviceSecret;
|
|
104523
|
+
await LocalForage.save(
|
|
104524
|
+
STORAGE_KEYS.encryptedShare2Device(this.orgHost, firebaseId),
|
|
104525
|
+
encryptedDevice
|
|
104526
|
+
);
|
|
104527
|
+
await LocalForage.save(
|
|
104528
|
+
STORAGE_KEYS.deviceSecret(this.orgHost, firebaseId),
|
|
104529
|
+
deviceSecret
|
|
104414
104530
|
);
|
|
104531
|
+
if (backup?.deviceId) {
|
|
104532
|
+
await LocalForage.save(
|
|
104533
|
+
STORAGE_KEYS.deviceId(this.orgHost, firebaseId),
|
|
104534
|
+
backup.deviceId
|
|
104535
|
+
);
|
|
104536
|
+
}
|
|
104415
104537
|
}
|
|
104416
104538
|
let share2;
|
|
104417
104539
|
try {
|
|
104418
|
-
share2 = Crypto.decryptShare(
|
|
104540
|
+
share2 = Crypto.decryptShare(
|
|
104541
|
+
encryptedDevice,
|
|
104542
|
+
deviceSecret,
|
|
104543
|
+
firebaseId
|
|
104544
|
+
);
|
|
104419
104545
|
} catch (e7) {
|
|
104420
104546
|
throw new SDKError(
|
|
104421
|
-
"PIN reset is not available
|
|
104547
|
+
"PIN reset is not available. Recovery material cannot be decrypted.",
|
|
104422
104548
|
"RECOVERY_NOT_AVAILABLE" /* RECOVERY_NOT_AVAILABLE */,
|
|
104423
104549
|
e7
|
|
104424
104550
|
);
|
|
104425
104551
|
}
|
|
104426
104552
|
const walletInfo = await this.walletClient.getWallet();
|
|
104553
|
+
const serverAddr = this.normalizeAddr(walletInfo?.address);
|
|
104427
104554
|
const privateKey = await Secrets.combine([
|
|
104428
104555
|
walletInfo.share1,
|
|
104429
104556
|
share2
|
|
104430
104557
|
]);
|
|
104431
104558
|
const wallet = new import_ethers2.Wallet(privateKey);
|
|
104432
|
-
const
|
|
104433
|
-
|
|
104434
|
-
const cachedAddr = await LocalForage.get(
|
|
104435
|
-
STORAGE_KEYS.walletAddress(this.orgHost)
|
|
104436
|
-
) ?? null;
|
|
104437
|
-
if (serverAddr && derivedAddr !== serverAddr) {
|
|
104559
|
+
const derivedAddr = this.normalizeAddr(wallet.address);
|
|
104560
|
+
if (this.addressesMismatch(serverAddr, derivedAddr)) {
|
|
104438
104561
|
throw new SDKError(
|
|
104439
|
-
`Device recovery
|
|
104562
|
+
`Device recovery does not match server wallet. server=${serverAddr} derived=${derivedAddr}`,
|
|
104440
104563
|
"RECOVERY_NOT_AVAILABLE" /* RECOVERY_NOT_AVAILABLE */
|
|
104441
104564
|
);
|
|
104442
104565
|
}
|
|
@@ -104476,8 +104599,23 @@ var WalletService = class {
|
|
|
104476
104599
|
await LocalForage.delete(STORAGE_KEYS.walletAddress(this.orgHost));
|
|
104477
104600
|
await LocalForage.delete(STORAGE_KEYS.share2(this.orgHost));
|
|
104478
104601
|
await LocalForage.delete(STORAGE_KEYS.encryptedShare2(this.orgHost));
|
|
104479
|
-
await LocalForage.
|
|
104480
|
-
|
|
104602
|
+
const firebaseId = await LocalForage.get(
|
|
104603
|
+
STORAGE_KEYS.firebaseId(this.orgHost)
|
|
104604
|
+
);
|
|
104605
|
+
if (firebaseId) {
|
|
104606
|
+
await LocalForage.delete(
|
|
104607
|
+
STORAGE_KEYS.encryptedShare2Device(this.orgHost, firebaseId)
|
|
104608
|
+
);
|
|
104609
|
+
await LocalForage.delete(
|
|
104610
|
+
STORAGE_KEYS.deviceSecret(this.orgHost, firebaseId)
|
|
104611
|
+
);
|
|
104612
|
+
await LocalForage.delete(STORAGE_KEYS.deviceId(this.orgHost, firebaseId));
|
|
104613
|
+
}
|
|
104614
|
+
await LocalForage.delete(
|
|
104615
|
+
STORAGE_KEYS.encryptedShare2DeviceLegacy(this.orgHost)
|
|
104616
|
+
);
|
|
104617
|
+
await LocalForage.delete(STORAGE_KEYS.deviceSecretLegacy(this.orgHost));
|
|
104618
|
+
await LocalForage.delete(STORAGE_KEYS.deviceIdLegacy(this.orgHost));
|
|
104481
104619
|
}
|
|
104482
104620
|
async getBalance(address, chainId) {
|
|
104483
104621
|
const response = await this.rpcClient.sendRpc({
|
|
@@ -104614,7 +104752,7 @@ var WalletService = class {
|
|
|
104614
104752
|
}
|
|
104615
104753
|
}
|
|
104616
104754
|
/**
|
|
104617
|
-
*
|
|
104755
|
+
* Critical safety:
|
|
104618
104756
|
* - Never overwrite cached walletAddress with derived signer address.
|
|
104619
104757
|
* - If server/cached address != derived address => throw WALLET_RECOVERY_FAILED.
|
|
104620
104758
|
*/
|
|
@@ -104642,19 +104780,21 @@ var WalletService = class {
|
|
|
104642
104780
|
const firebaseId = await LocalForage.get(
|
|
104643
104781
|
STORAGE_KEYS.firebaseId(this.orgHost)
|
|
104644
104782
|
);
|
|
104645
|
-
|
|
104646
|
-
|
|
104647
|
-
|
|
104648
|
-
const deviceSecret = await LocalForage.get(
|
|
104649
|
-
STORAGE_KEYS.deviceSecret(this.orgHost)
|
|
104650
|
-
);
|
|
104651
|
-
if (firebaseId && encryptedDevice && deviceSecret) {
|
|
104652
|
-
share2 = Crypto.decryptShare(
|
|
104653
|
-
encryptedDevice,
|
|
104654
|
-
deviceSecret,
|
|
104655
|
-
firebaseId
|
|
104783
|
+
if (firebaseId) {
|
|
104784
|
+
const encryptedDevice = await LocalForage.get(
|
|
104785
|
+
STORAGE_KEYS.encryptedShare2Device(this.orgHost, firebaseId)
|
|
104656
104786
|
);
|
|
104657
|
-
await LocalForage.
|
|
104787
|
+
const deviceSecret = await LocalForage.get(
|
|
104788
|
+
STORAGE_KEYS.deviceSecret(this.orgHost, firebaseId)
|
|
104789
|
+
);
|
|
104790
|
+
if (encryptedDevice && deviceSecret) {
|
|
104791
|
+
share2 = Crypto.decryptShare(
|
|
104792
|
+
encryptedDevice,
|
|
104793
|
+
deviceSecret,
|
|
104794
|
+
firebaseId
|
|
104795
|
+
);
|
|
104796
|
+
await LocalForage.save(STORAGE_KEYS.share2(this.orgHost), share2);
|
|
104797
|
+
}
|
|
104658
104798
|
}
|
|
104659
104799
|
} catch {
|
|
104660
104800
|
}
|
|
@@ -105243,6 +105383,38 @@ var WalletClient = class {
|
|
|
105243
105383
|
needsAccessToken: true
|
|
105244
105384
|
});
|
|
105245
105385
|
}
|
|
105386
|
+
async getDeviceShare2Backup() {
|
|
105387
|
+
try {
|
|
105388
|
+
return await this.client.get(
|
|
105389
|
+
"/api/v1/wallet/device-share2",
|
|
105390
|
+
{ needsAccessToken: true }
|
|
105391
|
+
);
|
|
105392
|
+
} catch (e7) {
|
|
105393
|
+
if (e7?.details?.status === 404 || String(e7?.message || "").includes("404"))
|
|
105394
|
+
return null;
|
|
105395
|
+
throw e7;
|
|
105396
|
+
}
|
|
105397
|
+
}
|
|
105398
|
+
async upsertDeviceShare2Backup(body) {
|
|
105399
|
+
await this.client.put("/api/v1/wallet/device-share2", body, {
|
|
105400
|
+
needsAccessToken: true
|
|
105401
|
+
});
|
|
105402
|
+
}
|
|
105403
|
+
async upsertDeviceRecovery(req) {
|
|
105404
|
+
await this.client.put(`${this.baseUrl}/device-recovery`, req, {
|
|
105405
|
+
needsAccessToken: true
|
|
105406
|
+
});
|
|
105407
|
+
}
|
|
105408
|
+
/**
|
|
105409
|
+
* If deviceId is omitted, server returns latest.
|
|
105410
|
+
* Returns { found:false } if no backup exists.
|
|
105411
|
+
*/
|
|
105412
|
+
async getDeviceRecovery(deviceId) {
|
|
105413
|
+
const qs = deviceId ? `?deviceId=${encodeURIComponent(deviceId)}` : "";
|
|
105414
|
+
return this.client.get(`${this.baseUrl}/device-recovery${qs}`, {
|
|
105415
|
+
needsAccessToken: true
|
|
105416
|
+
});
|
|
105417
|
+
}
|
|
105246
105418
|
};
|
|
105247
105419
|
|
|
105248
105420
|
// src/clients/api/rpcs.ts
|