@txnlab/use-wallet 4.5.0 → 4.6.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/index.cjs +189 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +189 -110
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5981,6 +5981,11 @@ var BaseWallet = class {
|
|
|
5981
5981
|
this.logger.error("Method not supported: signData");
|
|
5982
5982
|
throw new Error("Method not supported: signData");
|
|
5983
5983
|
};
|
|
5984
|
+
canUsePrivateKey = false;
|
|
5985
|
+
withPrivateKey = async (_callback) => {
|
|
5986
|
+
this.logger.error("Method not supported: withPrivateKey");
|
|
5987
|
+
throw new Error("Method not supported: withPrivateKey");
|
|
5988
|
+
};
|
|
5984
5989
|
// ---------- Derived Properties ------------------------------------ //
|
|
5985
5990
|
get name() {
|
|
5986
5991
|
return this.id.toUpperCase();
|
|
@@ -8234,6 +8239,116 @@ var MagicAuth = class extends BaseWallet {
|
|
|
8234
8239
|
|
|
8235
8240
|
// src/wallets/mnemonic.ts
|
|
8236
8241
|
var import_algosdk9 = __toESM(require("algosdk"), 1);
|
|
8242
|
+
|
|
8243
|
+
// src/secure-key.ts
|
|
8244
|
+
var secureLogger = logger.createScopedLogger("SecureKey");
|
|
8245
|
+
function zeroMemory(buffer) {
|
|
8246
|
+
if (!buffer || buffer.length === 0) return;
|
|
8247
|
+
try {
|
|
8248
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
8249
|
+
crypto.getRandomValues(buffer);
|
|
8250
|
+
}
|
|
8251
|
+
buffer.fill(0);
|
|
8252
|
+
} catch {
|
|
8253
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
8254
|
+
buffer[i] = 0;
|
|
8255
|
+
}
|
|
8256
|
+
}
|
|
8257
|
+
}
|
|
8258
|
+
function zeroString(str) {
|
|
8259
|
+
if (!str) return "";
|
|
8260
|
+
const arr = new Uint8Array(str.length);
|
|
8261
|
+
for (let i = 0; i < str.length; i++) {
|
|
8262
|
+
arr[i] = str.charCodeAt(i);
|
|
8263
|
+
}
|
|
8264
|
+
zeroMemory(arr);
|
|
8265
|
+
return "";
|
|
8266
|
+
}
|
|
8267
|
+
var SecureKeyContainer = class {
|
|
8268
|
+
_secretKey = null;
|
|
8269
|
+
_isCleared = false;
|
|
8270
|
+
constructor(secretKey) {
|
|
8271
|
+
this._secretKey = new Uint8Array(secretKey);
|
|
8272
|
+
}
|
|
8273
|
+
/**
|
|
8274
|
+
* Check if the key has been cleared
|
|
8275
|
+
*/
|
|
8276
|
+
get isCleared() {
|
|
8277
|
+
return this._isCleared;
|
|
8278
|
+
}
|
|
8279
|
+
/**
|
|
8280
|
+
* Execute a callback with access to the secret key.
|
|
8281
|
+
* The key is automatically cleared if an error occurs.
|
|
8282
|
+
*/
|
|
8283
|
+
async useKey(callback) {
|
|
8284
|
+
if (this._isCleared || !this._secretKey) {
|
|
8285
|
+
throw new Error("SecureKeyContainer: Key has been cleared");
|
|
8286
|
+
}
|
|
8287
|
+
try {
|
|
8288
|
+
return await callback(this._secretKey);
|
|
8289
|
+
} catch (error) {
|
|
8290
|
+
this.clear();
|
|
8291
|
+
throw error;
|
|
8292
|
+
}
|
|
8293
|
+
}
|
|
8294
|
+
/**
|
|
8295
|
+
* Execute a synchronous callback with access to the secret key.
|
|
8296
|
+
*/
|
|
8297
|
+
useKeySync(callback) {
|
|
8298
|
+
if (this._isCleared || !this._secretKey) {
|
|
8299
|
+
throw new Error("SecureKeyContainer: Key has been cleared");
|
|
8300
|
+
}
|
|
8301
|
+
try {
|
|
8302
|
+
return callback(this._secretKey);
|
|
8303
|
+
} catch (error) {
|
|
8304
|
+
this.clear();
|
|
8305
|
+
throw error;
|
|
8306
|
+
}
|
|
8307
|
+
}
|
|
8308
|
+
/**
|
|
8309
|
+
* Securely clear the key from memory.
|
|
8310
|
+
* This should be called when the key is no longer needed.
|
|
8311
|
+
*/
|
|
8312
|
+
clear() {
|
|
8313
|
+
if (this._secretKey && !this._isCleared) {
|
|
8314
|
+
zeroMemory(this._secretKey);
|
|
8315
|
+
this._secretKey = null;
|
|
8316
|
+
this._isCleared = true;
|
|
8317
|
+
secureLogger.debug("Key material cleared from memory");
|
|
8318
|
+
}
|
|
8319
|
+
}
|
|
8320
|
+
};
|
|
8321
|
+
async function withSecureKey(secretKey, callback) {
|
|
8322
|
+
const container = new SecureKeyContainer(secretKey);
|
|
8323
|
+
try {
|
|
8324
|
+
return await callback(container);
|
|
8325
|
+
} finally {
|
|
8326
|
+
container.clear();
|
|
8327
|
+
}
|
|
8328
|
+
}
|
|
8329
|
+
function withSecureKeySync(secretKey, callback) {
|
|
8330
|
+
const container = new SecureKeyContainer(secretKey);
|
|
8331
|
+
try {
|
|
8332
|
+
return callback(container);
|
|
8333
|
+
} finally {
|
|
8334
|
+
container.clear();
|
|
8335
|
+
}
|
|
8336
|
+
}
|
|
8337
|
+
async function deriveAlgorandAccountFromEd25519(ed25519Seed) {
|
|
8338
|
+
if (ed25519Seed.length !== 32) {
|
|
8339
|
+
throw new Error(`Invalid ed25519 seed length: expected 32 bytes, got ${ed25519Seed.length}`);
|
|
8340
|
+
}
|
|
8341
|
+
const nacl = await Promise.resolve().then(() => __toESM(require_nacl_fast(), 1));
|
|
8342
|
+
const algosdk15 = await import("algosdk");
|
|
8343
|
+
const keyPair = nacl.sign.keyPair.fromSeed(ed25519Seed);
|
|
8344
|
+
const address = algosdk15.encodeAddress(keyPair.publicKey);
|
|
8345
|
+
return {
|
|
8346
|
+
addr: address,
|
|
8347
|
+
sk: keyPair.secretKey
|
|
8348
|
+
};
|
|
8349
|
+
}
|
|
8350
|
+
|
|
8351
|
+
// src/wallets/mnemonic.ts
|
|
8237
8352
|
var LOCAL_STORAGE_MNEMONIC_KEY = `${LOCAL_STORAGE_KEY}_mnemonic`;
|
|
8238
8353
|
var ICON11 = `data:image/svg+xml;base64,${btoa(`
|
|
8239
8354
|
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
|
|
@@ -8387,6 +8502,41 @@ var MnemonicWallet = class extends BaseWallet {
|
|
|
8387
8502
|
});
|
|
8388
8503
|
return txnsToSign;
|
|
8389
8504
|
}
|
|
8505
|
+
canUsePrivateKey = true;
|
|
8506
|
+
/**
|
|
8507
|
+
* Provide scoped access to the private key via a callback.
|
|
8508
|
+
*
|
|
8509
|
+
* The callback receives a copy of the 64-byte Algorand secret key.
|
|
8510
|
+
* The copy is guaranteed to be zeroed from memory when the callback
|
|
8511
|
+
* completes, whether it succeeds or throws.
|
|
8512
|
+
*
|
|
8513
|
+
* **Note:** This method is blocked on MainNet. The Mnemonic wallet is intended
|
|
8514
|
+
* for development and testing only. For production use, see Web3Auth which
|
|
8515
|
+
* supports `withPrivateKey` on all networks.
|
|
8516
|
+
*
|
|
8517
|
+
* @example
|
|
8518
|
+
* ```typescript
|
|
8519
|
+
* const result = await wallet.withPrivateKey(async (secretKey) => {
|
|
8520
|
+
* // secretKey is a 64-byte Uint8Array
|
|
8521
|
+
* return doSomethingWith(secretKey)
|
|
8522
|
+
* })
|
|
8523
|
+
* // secretKey is zeroed at this point
|
|
8524
|
+
* ```
|
|
8525
|
+
*/
|
|
8526
|
+
withPrivateKey = async (callback) => {
|
|
8527
|
+
this.checkMainnet();
|
|
8528
|
+
if (!this.account) {
|
|
8529
|
+
this.logger.error("Mnemonic wallet not connected");
|
|
8530
|
+
throw new Error("Mnemonic wallet not connected");
|
|
8531
|
+
}
|
|
8532
|
+
this.logger.debug("withPrivateKey: Providing private key access...");
|
|
8533
|
+
const skCopy = new Uint8Array(this.account.sk);
|
|
8534
|
+
try {
|
|
8535
|
+
return await callback(skCopy);
|
|
8536
|
+
} finally {
|
|
8537
|
+
zeroMemory(skCopy);
|
|
8538
|
+
}
|
|
8539
|
+
};
|
|
8390
8540
|
signTransactions = async (txnGroup, indexesToSign) => {
|
|
8391
8541
|
this.checkMainnet();
|
|
8392
8542
|
try {
|
|
@@ -8626,116 +8776,6 @@ var PeraWallet = class extends BaseWallet {
|
|
|
8626
8776
|
|
|
8627
8777
|
// src/wallets/web3auth.ts
|
|
8628
8778
|
var import_algosdk11 = __toESM(require("algosdk"), 1);
|
|
8629
|
-
|
|
8630
|
-
// src/secure-key.ts
|
|
8631
|
-
var secureLogger = logger.createScopedLogger("SecureKey");
|
|
8632
|
-
function zeroMemory(buffer) {
|
|
8633
|
-
if (!buffer || buffer.length === 0) return;
|
|
8634
|
-
try {
|
|
8635
|
-
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
8636
|
-
crypto.getRandomValues(buffer);
|
|
8637
|
-
}
|
|
8638
|
-
buffer.fill(0);
|
|
8639
|
-
} catch {
|
|
8640
|
-
for (let i = 0; i < buffer.length; i++) {
|
|
8641
|
-
buffer[i] = 0;
|
|
8642
|
-
}
|
|
8643
|
-
}
|
|
8644
|
-
}
|
|
8645
|
-
function zeroString(str) {
|
|
8646
|
-
if (!str) return "";
|
|
8647
|
-
const arr = new Uint8Array(str.length);
|
|
8648
|
-
for (let i = 0; i < str.length; i++) {
|
|
8649
|
-
arr[i] = str.charCodeAt(i);
|
|
8650
|
-
}
|
|
8651
|
-
zeroMemory(arr);
|
|
8652
|
-
return "";
|
|
8653
|
-
}
|
|
8654
|
-
var SecureKeyContainer = class {
|
|
8655
|
-
_secretKey = null;
|
|
8656
|
-
_isCleared = false;
|
|
8657
|
-
constructor(secretKey) {
|
|
8658
|
-
this._secretKey = new Uint8Array(secretKey);
|
|
8659
|
-
}
|
|
8660
|
-
/**
|
|
8661
|
-
* Check if the key has been cleared
|
|
8662
|
-
*/
|
|
8663
|
-
get isCleared() {
|
|
8664
|
-
return this._isCleared;
|
|
8665
|
-
}
|
|
8666
|
-
/**
|
|
8667
|
-
* Execute a callback with access to the secret key.
|
|
8668
|
-
* The key is automatically cleared if an error occurs.
|
|
8669
|
-
*/
|
|
8670
|
-
async useKey(callback) {
|
|
8671
|
-
if (this._isCleared || !this._secretKey) {
|
|
8672
|
-
throw new Error("SecureKeyContainer: Key has been cleared");
|
|
8673
|
-
}
|
|
8674
|
-
try {
|
|
8675
|
-
return await callback(this._secretKey);
|
|
8676
|
-
} catch (error) {
|
|
8677
|
-
this.clear();
|
|
8678
|
-
throw error;
|
|
8679
|
-
}
|
|
8680
|
-
}
|
|
8681
|
-
/**
|
|
8682
|
-
* Execute a synchronous callback with access to the secret key.
|
|
8683
|
-
*/
|
|
8684
|
-
useKeySync(callback) {
|
|
8685
|
-
if (this._isCleared || !this._secretKey) {
|
|
8686
|
-
throw new Error("SecureKeyContainer: Key has been cleared");
|
|
8687
|
-
}
|
|
8688
|
-
try {
|
|
8689
|
-
return callback(this._secretKey);
|
|
8690
|
-
} catch (error) {
|
|
8691
|
-
this.clear();
|
|
8692
|
-
throw error;
|
|
8693
|
-
}
|
|
8694
|
-
}
|
|
8695
|
-
/**
|
|
8696
|
-
* Securely clear the key from memory.
|
|
8697
|
-
* This should be called when the key is no longer needed.
|
|
8698
|
-
*/
|
|
8699
|
-
clear() {
|
|
8700
|
-
if (this._secretKey && !this._isCleared) {
|
|
8701
|
-
zeroMemory(this._secretKey);
|
|
8702
|
-
this._secretKey = null;
|
|
8703
|
-
this._isCleared = true;
|
|
8704
|
-
secureLogger.debug("Key material cleared from memory");
|
|
8705
|
-
}
|
|
8706
|
-
}
|
|
8707
|
-
};
|
|
8708
|
-
async function withSecureKey(secretKey, callback) {
|
|
8709
|
-
const container = new SecureKeyContainer(secretKey);
|
|
8710
|
-
try {
|
|
8711
|
-
return await callback(container);
|
|
8712
|
-
} finally {
|
|
8713
|
-
container.clear();
|
|
8714
|
-
}
|
|
8715
|
-
}
|
|
8716
|
-
function withSecureKeySync(secretKey, callback) {
|
|
8717
|
-
const container = new SecureKeyContainer(secretKey);
|
|
8718
|
-
try {
|
|
8719
|
-
return callback(container);
|
|
8720
|
-
} finally {
|
|
8721
|
-
container.clear();
|
|
8722
|
-
}
|
|
8723
|
-
}
|
|
8724
|
-
async function deriveAlgorandAccountFromEd25519(ed25519Seed) {
|
|
8725
|
-
if (ed25519Seed.length !== 32) {
|
|
8726
|
-
throw new Error(`Invalid ed25519 seed length: expected 32 bytes, got ${ed25519Seed.length}`);
|
|
8727
|
-
}
|
|
8728
|
-
const nacl = await Promise.resolve().then(() => __toESM(require_nacl_fast(), 1));
|
|
8729
|
-
const algosdk15 = await import("algosdk");
|
|
8730
|
-
const keyPair = nacl.sign.keyPair.fromSeed(ed25519Seed);
|
|
8731
|
-
const address = algosdk15.encodeAddress(keyPair.publicKey);
|
|
8732
|
-
return {
|
|
8733
|
-
addr: address,
|
|
8734
|
-
sk: keyPair.secretKey
|
|
8735
|
-
};
|
|
8736
|
-
}
|
|
8737
|
-
|
|
8738
|
-
// src/wallets/web3auth.ts
|
|
8739
8779
|
var LOCAL_STORAGE_WEB3AUTH_KEY = `${LOCAL_STORAGE_KEY}:web3auth`;
|
|
8740
8780
|
var ICON13 = `data:image/svg+xml;base64,${btoa(`
|
|
8741
8781
|
<svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
|
@@ -9251,6 +9291,45 @@ var Web3AuthWallet = class extends BaseWallet {
|
|
|
9251
9291
|
});
|
|
9252
9292
|
return txnsToSign;
|
|
9253
9293
|
}
|
|
9294
|
+
canUsePrivateKey = true;
|
|
9295
|
+
/**
|
|
9296
|
+
* Provide scoped access to the private key via a callback.
|
|
9297
|
+
*
|
|
9298
|
+
* The callback receives a 64-byte Algorand secret key (ed25519 seed + public key).
|
|
9299
|
+
* The key is a fresh copy that is guaranteed to be zeroed from memory when the
|
|
9300
|
+
* callback completes, whether it succeeds or throws.
|
|
9301
|
+
*
|
|
9302
|
+
* SECURITY: The key is fetched fresh from Web3Auth for each call and never cached.
|
|
9303
|
+
*
|
|
9304
|
+
* @example
|
|
9305
|
+
* ```typescript
|
|
9306
|
+
* const result = await wallet.withPrivateKey(async (secretKey) => {
|
|
9307
|
+
* // secretKey is a 64-byte Uint8Array
|
|
9308
|
+
* // Use for custom signing, authentication, etc.
|
|
9309
|
+
* return doSomethingWith(secretKey)
|
|
9310
|
+
* })
|
|
9311
|
+
* // secretKey is zeroed at this point
|
|
9312
|
+
* ```
|
|
9313
|
+
*/
|
|
9314
|
+
withPrivateKey = async (callback) => {
|
|
9315
|
+
this.logger.debug("withPrivateKey: Providing private key access...");
|
|
9316
|
+
await this.ensureConnected();
|
|
9317
|
+
const keyContainer = await this.getSecureKey();
|
|
9318
|
+
try {
|
|
9319
|
+
return await keyContainer.useKey(async (secretKey) => {
|
|
9320
|
+
const account = await deriveAlgorandAccountFromEd25519(secretKey);
|
|
9321
|
+
const skCopy = new Uint8Array(account.sk);
|
|
9322
|
+
zeroMemory(account.sk);
|
|
9323
|
+
try {
|
|
9324
|
+
return await callback(skCopy);
|
|
9325
|
+
} finally {
|
|
9326
|
+
zeroMemory(skCopy);
|
|
9327
|
+
}
|
|
9328
|
+
});
|
|
9329
|
+
} finally {
|
|
9330
|
+
keyContainer.clear();
|
|
9331
|
+
}
|
|
9332
|
+
};
|
|
9254
9333
|
/**
|
|
9255
9334
|
* Sign transactions
|
|
9256
9335
|
*
|