@txnlab/use-wallet-mnemonic 5.0.0-rc.4 → 5.0.1
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.d.ts +4 -5
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import algosdk from "algosdk";
|
|
2
2
|
import { AdapterConstructorParams, BaseWallet, WalletAccount, WalletMetadata } from "@txnlab/use-wallet/adapter";
|
|
3
3
|
import { WalletAdapterConfig, WalletFactoryOptions } from "@txnlab/use-wallet";
|
|
4
|
-
|
|
5
4
|
//#region src/adapter.d.ts
|
|
6
5
|
interface MnemonicConstructor {
|
|
7
6
|
persistToStorage?: boolean;
|
|
8
7
|
promptForMnemonic: () => Promise<string | null>;
|
|
9
8
|
}
|
|
10
9
|
type MnemonicOptions = Partial<Pick<MnemonicConstructor, 'promptForMnemonic'>> & Omit<MnemonicConstructor, 'promptForMnemonic'>;
|
|
11
|
-
declare class MnemonicAdapter extends BaseWallet<MnemonicOptions> {
|
|
10
|
+
export declare class MnemonicAdapter extends BaseWallet<MnemonicOptions> {
|
|
12
11
|
private account;
|
|
13
12
|
private mnemonicOptions;
|
|
14
13
|
constructor(params: AdapterConstructorParams<MnemonicOptions>);
|
|
@@ -49,8 +48,8 @@ declare class MnemonicAdapter extends BaseWallet<MnemonicOptions> {
|
|
|
49
48
|
}
|
|
50
49
|
//#endregion
|
|
51
50
|
//#region src/index.d.ts
|
|
52
|
-
declare const WALLET_ID: "mnemonic";
|
|
53
|
-
declare function mnemonic(options?: MnemonicOptions & WalletFactoryOptions): WalletAdapterConfig;
|
|
51
|
+
export declare const WALLET_ID: "mnemonic";
|
|
52
|
+
export declare function mnemonic(options?: MnemonicOptions & WalletFactoryOptions): WalletAdapterConfig;
|
|
54
53
|
//#endregion
|
|
55
|
-
export {
|
|
54
|
+
export type { MnemonicOptions };
|
|
56
55
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -123,7 +123,8 @@ var MnemonicAdapter = class extends BaseWallet {
|
|
|
123
123
|
processEncodedTxns(txnGroup, indexesToSign) {
|
|
124
124
|
const txnsToSign = [];
|
|
125
125
|
txnGroup.forEach((txnBuffer, index) => {
|
|
126
|
-
const
|
|
126
|
+
const decodedObj = algosdk.msgpackRawDecode(txnBuffer);
|
|
127
|
+
const isSigned = isSignedTxn(decodedObj);
|
|
127
128
|
const txn = isSigned ? algosdk.decodeSignedTransaction(txnBuffer).txn : algosdk.decodeUnsignedTransaction(txnBuffer);
|
|
128
129
|
const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
|
|
129
130
|
const signer = txn.sender.toString();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/icon.ts","../src/adapter.ts","../src/index.ts"],"sourcesContent":["export const icon = `\n<svg viewBox=\"0 0 400 400\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect fill=\"#525252\" width=\"400\" height=\"400\" />\n <path fill=\"#FFFFFF\" d=\"M309.2,309.3H275l-22.2-82.7l-47.9,82.7h-38.3l73.9-128l-11.9-44.5l-99.6,172.6H90.8L217.1,90.6 h33.5l14.7,54.3h34.6l-23.6,41L309.2,309.3z\" />\n</svg>\n`\n","import algosdk from 'algosdk'\nimport {\n BaseWallet,\n flattenTxnGroup,\n isSignedTxn,\n isTransactionArray,\n zeroMemory,\n type AdapterConstructorParams,\n type WalletAccount,\n type WalletMetadata,\n type WalletState\n} from '@txnlab/use-wallet/adapter'\n\ninterface MnemonicConstructor {\n persistToStorage?: boolean\n promptForMnemonic: () => Promise<string | null>\n}\n\nexport type MnemonicOptions = Partial<Pick<MnemonicConstructor, 'promptForMnemonic'>> &\n Omit<MnemonicConstructor, 'promptForMnemonic'>\n\nexport const LOCAL_STORAGE_MNEMONIC_KEY = '@txnlab/use-wallet:v5_mnemonic'\n\nimport { icon } from './icon'\n\nconst ICON = `data:image/svg+xml;base64,${btoa(icon)}`\n\nexport class MnemonicAdapter extends BaseWallet<MnemonicOptions> {\n private account: algosdk.Account | null = null\n private mnemonicOptions: MnemonicConstructor\n\n constructor(params: AdapterConstructorParams<MnemonicOptions>) {\n super(params)\n\n const {\n persistToStorage = false,\n promptForMnemonic = () => Promise.resolve(prompt('Enter 25-word mnemonic passphrase:'))\n } = this.options || {}\n\n this.mnemonicOptions = { persistToStorage, promptForMnemonic }\n\n if (this.mnemonicOptions.persistToStorage) {\n this.logger.warn(\n 'Persisting mnemonics to storage is insecure. Any private key mnemonics used should never hold real Algos (i.e., on MainNet). Use with caution!'\n )\n }\n }\n\n static defaultMetadata: WalletMetadata = {\n name: 'Mnemonic',\n icon: ICON\n }\n\n private loadMnemonicFromStorage(): string | null {\n if (typeof localStorage === 'undefined') return null\n return localStorage.getItem(LOCAL_STORAGE_MNEMONIC_KEY)\n }\n\n private saveMnemonicToStorage(mnemonic: string): void {\n if (typeof localStorage === 'undefined') return\n localStorage.setItem(LOCAL_STORAGE_MNEMONIC_KEY, mnemonic)\n }\n\n private removeMnemonicFromStorage(): void {\n if (typeof localStorage === 'undefined') return\n localStorage.removeItem(LOCAL_STORAGE_MNEMONIC_KEY)\n }\n\n private checkMainnet(): void {\n try {\n const network = this.activeNetworkConfig\n if (!network.isTestnet) {\n this.logger.warn(\n 'The Mnemonic wallet provider is insecure and intended for testing only. Any private key mnemonics used should never hold real Algos (i.e., on MainNet).'\n )\n throw new Error('Production network detected. Aborting.')\n }\n } catch (error) {\n this.disconnect()\n throw error\n }\n }\n\n private async initializeAccount(): Promise<algosdk.Account> {\n let mnemonic = this.loadMnemonicFromStorage()\n if (!mnemonic) {\n mnemonic = await this.mnemonicOptions.promptForMnemonic()\n if (!mnemonic) {\n this.account = null\n this.logger.error('No mnemonic provided')\n throw new Error('No mnemonic provided')\n }\n\n if (this.mnemonicOptions.persistToStorage) {\n this.logger.warn('Mnemonic saved to localStorage.')\n this.saveMnemonicToStorage(mnemonic)\n }\n }\n\n const account = algosdk.mnemonicToSecretKey(mnemonic)\n this.account = account\n return account\n }\n\n public connect = async (): Promise<WalletAccount[]> => {\n // Throw error if MainNet is active\n this.checkMainnet()\n\n this.logger.info('Connecting...')\n const account = await this.initializeAccount()\n\n const walletAccount = {\n name: `${this.metadata.name} Account`,\n address: account.addr.toString()\n }\n\n const walletState: WalletState = {\n accounts: [walletAccount],\n activeAccount: walletAccount\n }\n\n this.store.addWallet(walletState)\n\n this.logger.info('Connected successfully', walletState)\n return [walletAccount]\n }\n\n public disconnect = async (): Promise<void> => {\n this.logger.info('Disconnecting...')\n this.onDisconnect()\n this.account = null\n this.removeMnemonicFromStorage()\n this.logger.info('Disconnected')\n }\n\n public resumeSession = async (): Promise<void> => {\n // Throw error if MainNet is active\n this.checkMainnet()\n\n const walletState = this.store.getWalletState()\n\n // No session to resume\n if (!walletState) {\n this.logger.info('No session to resume')\n return\n }\n\n this.logger.info('Resuming session...')\n\n // If persisting to storage is enabled, then resume session\n if (this.mnemonicOptions.persistToStorage) {\n try {\n await this.initializeAccount()\n this.logger.info('Session resumed successfully')\n } catch (error: any) {\n this.logger.error('Error resuming session:', error.message)\n this.disconnect()\n throw error\n }\n } else {\n // Otherwise, do not resume session, disconnect instead\n this.logger.info('No session to resume, disconnecting...')\n this.disconnect()\n }\n }\n\n private processTxns(\n txnGroup: algosdk.Transaction[],\n indexesToSign?: number[]\n ): algosdk.Transaction[] {\n const txnsToSign: algosdk.Transaction[] = []\n\n txnGroup.forEach((txn, index) => {\n const isIndexMatch = !indexesToSign || indexesToSign.includes(index)\n const signer = txn.sender.toString()\n const canSignTxn = signer === this.account!.addr.toString()\n\n if (isIndexMatch && canSignTxn) {\n txnsToSign.push(txn)\n }\n })\n\n return txnsToSign\n }\n\n private processEncodedTxns(\n txnGroup: Uint8Array[],\n indexesToSign?: number[]\n ): algosdk.Transaction[] {\n const txnsToSign: algosdk.Transaction[] = []\n\n txnGroup.forEach((txnBuffer, index) => {\n const decodedObj = algosdk.msgpackRawDecode(txnBuffer)\n const isSigned = isSignedTxn(decodedObj)\n\n const txn: algosdk.Transaction = isSigned\n ? algosdk.decodeSignedTransaction(txnBuffer).txn\n : algosdk.decodeUnsignedTransaction(txnBuffer)\n\n const isIndexMatch = !indexesToSign || indexesToSign.includes(index)\n const signer = txn.sender.toString()\n const canSignTxn = !isSigned && signer === this.account!.addr.toString()\n\n if (isIndexMatch && canSignTxn) {\n txnsToSign.push(txn)\n }\n })\n\n return txnsToSign\n }\n\n public canUsePrivateKey = true\n\n /**\n * Provide scoped access to the private key via a callback.\n *\n * The callback receives a copy of the 64-byte Algorand secret key.\n * The copy is guaranteed to be zeroed from memory when the callback\n * completes, whether it succeeds or throws.\n *\n * **Note:** This method is blocked on MainNet. The Mnemonic wallet is intended\n * for development and testing only. For production use, see Web3Auth which\n * supports `withPrivateKey` on all networks.\n *\n * @example\n * ```typescript\n * const result = await wallet.withPrivateKey(async (secretKey) => {\n * // secretKey is a 64-byte Uint8Array\n * return doSomethingWith(secretKey)\n * })\n * // secretKey is zeroed at this point\n * ```\n */\n public withPrivateKey = async <T>(\n callback: (secretKey: Uint8Array) => Promise<T>\n ): Promise<T> => {\n // Throw error if MainNet is active\n this.checkMainnet()\n\n if (!this.account) {\n this.logger.error('Mnemonic wallet not connected')\n throw new Error('Mnemonic wallet not connected')\n }\n\n this.logger.debug('withPrivateKey: Providing private key access...')\n\n // Create a copy of the secret key for the consumer\n const skCopy = new Uint8Array(this.account.sk)\n\n try {\n return await callback(skCopy)\n } finally {\n // SECURITY: Always zero the consumer's copy\n zeroMemory(skCopy)\n }\n }\n\n public signTransactions = async <T extends algosdk.Transaction[] | Uint8Array[]>(\n txnGroup: T | T[],\n indexesToSign?: number[]\n ): Promise<(Uint8Array | null)[]> => {\n // Throw error if MainNet is active\n this.checkMainnet()\n\n try {\n this.logger.debug('Signing transactions...', { txnGroup, indexesToSign })\n let txnsToSign: algosdk.Transaction[] = []\n\n // Determine type and process transactions for signing\n if (isTransactionArray(txnGroup)) {\n const flatTxns: algosdk.Transaction[] = flattenTxnGroup(txnGroup)\n txnsToSign = this.processTxns(flatTxns, indexesToSign)\n } else {\n const flatTxns: Uint8Array[] = flattenTxnGroup(txnGroup as Uint8Array[])\n txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign)\n }\n\n // Sign transactions\n const signedTxns = txnsToSign.map((txn) => txn.signTxn(this.account!.sk))\n this.logger.debug('Transactions signed successfully', { signedTxns })\n return signedTxns\n } catch (error: any) {\n this.logger.error('Error signing transactions:', error.message)\n throw error\n }\n }\n}\n","import { MnemonicAdapter } from './adapter'\nimport type { MnemonicOptions } from './adapter'\nimport type { WalletAdapterConfig, WalletFactoryOptions } from '@txnlab/use-wallet'\n\nexport const WALLET_ID = 'mnemonic' as const\n\nexport function mnemonic(options?: MnemonicOptions & WalletFactoryOptions): WalletAdapterConfig {\n const { metadata, ...adapterOptions } = options ?? {}\n return {\n id: WALLET_ID,\n metadata: { ...MnemonicAdapter.defaultMetadata, ...metadata },\n Adapter: MnemonicAdapter as unknown as WalletAdapterConfig['Adapter'],\n options:\n Object.keys(adapterOptions).length > 0\n ? (adapterOptions as unknown as Record<string, unknown>)\n : undefined,\n capabilities: { excludedNetworks: ['mainnet'] }\n }\n}\n\nexport { MnemonicAdapter }\nexport type { MnemonicOptions }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/icon.ts","../src/adapter.ts","../src/index.ts"],"sourcesContent":["export const icon = `\n<svg viewBox=\"0 0 400 400\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect fill=\"#525252\" width=\"400\" height=\"400\" />\n <path fill=\"#FFFFFF\" d=\"M309.2,309.3H275l-22.2-82.7l-47.9,82.7h-38.3l73.9-128l-11.9-44.5l-99.6,172.6H90.8L217.1,90.6 h33.5l14.7,54.3h34.6l-23.6,41L309.2,309.3z\" />\n</svg>\n`\n","import algosdk from 'algosdk'\nimport {\n BaseWallet,\n flattenTxnGroup,\n isSignedTxn,\n isTransactionArray,\n zeroMemory,\n type AdapterConstructorParams,\n type WalletAccount,\n type WalletMetadata,\n type WalletState\n} from '@txnlab/use-wallet/adapter'\n\ninterface MnemonicConstructor {\n persistToStorage?: boolean\n promptForMnemonic: () => Promise<string | null>\n}\n\nexport type MnemonicOptions = Partial<Pick<MnemonicConstructor, 'promptForMnemonic'>> &\n Omit<MnemonicConstructor, 'promptForMnemonic'>\n\nexport const LOCAL_STORAGE_MNEMONIC_KEY = '@txnlab/use-wallet:v5_mnemonic'\n\nimport { icon } from './icon'\n\nconst ICON = `data:image/svg+xml;base64,${btoa(icon)}`\n\nexport class MnemonicAdapter extends BaseWallet<MnemonicOptions> {\n private account: algosdk.Account | null = null\n private mnemonicOptions: MnemonicConstructor\n\n constructor(params: AdapterConstructorParams<MnemonicOptions>) {\n super(params)\n\n const {\n persistToStorage = false,\n promptForMnemonic = () => Promise.resolve(prompt('Enter 25-word mnemonic passphrase:'))\n } = this.options || {}\n\n this.mnemonicOptions = { persistToStorage, promptForMnemonic }\n\n if (this.mnemonicOptions.persistToStorage) {\n this.logger.warn(\n 'Persisting mnemonics to storage is insecure. Any private key mnemonics used should never hold real Algos (i.e., on MainNet). Use with caution!'\n )\n }\n }\n\n static defaultMetadata: WalletMetadata = {\n name: 'Mnemonic',\n icon: ICON\n }\n\n private loadMnemonicFromStorage(): string | null {\n if (typeof localStorage === 'undefined') return null\n return localStorage.getItem(LOCAL_STORAGE_MNEMONIC_KEY)\n }\n\n private saveMnemonicToStorage(mnemonic: string): void {\n if (typeof localStorage === 'undefined') return\n localStorage.setItem(LOCAL_STORAGE_MNEMONIC_KEY, mnemonic)\n }\n\n private removeMnemonicFromStorage(): void {\n if (typeof localStorage === 'undefined') return\n localStorage.removeItem(LOCAL_STORAGE_MNEMONIC_KEY)\n }\n\n private checkMainnet(): void {\n try {\n const network = this.activeNetworkConfig\n if (!network.isTestnet) {\n this.logger.warn(\n 'The Mnemonic wallet provider is insecure and intended for testing only. Any private key mnemonics used should never hold real Algos (i.e., on MainNet).'\n )\n throw new Error('Production network detected. Aborting.')\n }\n } catch (error) {\n this.disconnect()\n throw error\n }\n }\n\n private async initializeAccount(): Promise<algosdk.Account> {\n let mnemonic = this.loadMnemonicFromStorage()\n if (!mnemonic) {\n mnemonic = await this.mnemonicOptions.promptForMnemonic()\n if (!mnemonic) {\n this.account = null\n this.logger.error('No mnemonic provided')\n throw new Error('No mnemonic provided')\n }\n\n if (this.mnemonicOptions.persistToStorage) {\n this.logger.warn('Mnemonic saved to localStorage.')\n this.saveMnemonicToStorage(mnemonic)\n }\n }\n\n const account = algosdk.mnemonicToSecretKey(mnemonic)\n this.account = account\n return account\n }\n\n public connect = async (): Promise<WalletAccount[]> => {\n // Throw error if MainNet is active\n this.checkMainnet()\n\n this.logger.info('Connecting...')\n const account = await this.initializeAccount()\n\n const walletAccount = {\n name: `${this.metadata.name} Account`,\n address: account.addr.toString()\n }\n\n const walletState: WalletState = {\n accounts: [walletAccount],\n activeAccount: walletAccount\n }\n\n this.store.addWallet(walletState)\n\n this.logger.info('Connected successfully', walletState)\n return [walletAccount]\n }\n\n public disconnect = async (): Promise<void> => {\n this.logger.info('Disconnecting...')\n this.onDisconnect()\n this.account = null\n this.removeMnemonicFromStorage()\n this.logger.info('Disconnected')\n }\n\n public resumeSession = async (): Promise<void> => {\n // Throw error if MainNet is active\n this.checkMainnet()\n\n const walletState = this.store.getWalletState()\n\n // No session to resume\n if (!walletState) {\n this.logger.info('No session to resume')\n return\n }\n\n this.logger.info('Resuming session...')\n\n // If persisting to storage is enabled, then resume session\n if (this.mnemonicOptions.persistToStorage) {\n try {\n await this.initializeAccount()\n this.logger.info('Session resumed successfully')\n } catch (error: any) {\n this.logger.error('Error resuming session:', error.message)\n this.disconnect()\n throw error\n }\n } else {\n // Otherwise, do not resume session, disconnect instead\n this.logger.info('No session to resume, disconnecting...')\n this.disconnect()\n }\n }\n\n private processTxns(\n txnGroup: algosdk.Transaction[],\n indexesToSign?: number[]\n ): algosdk.Transaction[] {\n const txnsToSign: algosdk.Transaction[] = []\n\n txnGroup.forEach((txn, index) => {\n const isIndexMatch = !indexesToSign || indexesToSign.includes(index)\n const signer = txn.sender.toString()\n const canSignTxn = signer === this.account!.addr.toString()\n\n if (isIndexMatch && canSignTxn) {\n txnsToSign.push(txn)\n }\n })\n\n return txnsToSign\n }\n\n private processEncodedTxns(\n txnGroup: Uint8Array[],\n indexesToSign?: number[]\n ): algosdk.Transaction[] {\n const txnsToSign: algosdk.Transaction[] = []\n\n txnGroup.forEach((txnBuffer, index) => {\n const decodedObj = algosdk.msgpackRawDecode(txnBuffer)\n const isSigned = isSignedTxn(decodedObj)\n\n const txn: algosdk.Transaction = isSigned\n ? algosdk.decodeSignedTransaction(txnBuffer).txn\n : algosdk.decodeUnsignedTransaction(txnBuffer)\n\n const isIndexMatch = !indexesToSign || indexesToSign.includes(index)\n const signer = txn.sender.toString()\n const canSignTxn = !isSigned && signer === this.account!.addr.toString()\n\n if (isIndexMatch && canSignTxn) {\n txnsToSign.push(txn)\n }\n })\n\n return txnsToSign\n }\n\n public canUsePrivateKey = true\n\n /**\n * Provide scoped access to the private key via a callback.\n *\n * The callback receives a copy of the 64-byte Algorand secret key.\n * The copy is guaranteed to be zeroed from memory when the callback\n * completes, whether it succeeds or throws.\n *\n * **Note:** This method is blocked on MainNet. The Mnemonic wallet is intended\n * for development and testing only. For production use, see Web3Auth which\n * supports `withPrivateKey` on all networks.\n *\n * @example\n * ```typescript\n * const result = await wallet.withPrivateKey(async (secretKey) => {\n * // secretKey is a 64-byte Uint8Array\n * return doSomethingWith(secretKey)\n * })\n * // secretKey is zeroed at this point\n * ```\n */\n public withPrivateKey = async <T>(\n callback: (secretKey: Uint8Array) => Promise<T>\n ): Promise<T> => {\n // Throw error if MainNet is active\n this.checkMainnet()\n\n if (!this.account) {\n this.logger.error('Mnemonic wallet not connected')\n throw new Error('Mnemonic wallet not connected')\n }\n\n this.logger.debug('withPrivateKey: Providing private key access...')\n\n // Create a copy of the secret key for the consumer\n const skCopy = new Uint8Array(this.account.sk)\n\n try {\n return await callback(skCopy)\n } finally {\n // SECURITY: Always zero the consumer's copy\n zeroMemory(skCopy)\n }\n }\n\n public signTransactions = async <T extends algosdk.Transaction[] | Uint8Array[]>(\n txnGroup: T | T[],\n indexesToSign?: number[]\n ): Promise<(Uint8Array | null)[]> => {\n // Throw error if MainNet is active\n this.checkMainnet()\n\n try {\n this.logger.debug('Signing transactions...', { txnGroup, indexesToSign })\n let txnsToSign: algosdk.Transaction[] = []\n\n // Determine type and process transactions for signing\n if (isTransactionArray(txnGroup)) {\n const flatTxns: algosdk.Transaction[] = flattenTxnGroup(txnGroup)\n txnsToSign = this.processTxns(flatTxns, indexesToSign)\n } else {\n const flatTxns: Uint8Array[] = flattenTxnGroup(txnGroup as Uint8Array[])\n txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign)\n }\n\n // Sign transactions\n const signedTxns = txnsToSign.map((txn) => txn.signTxn(this.account!.sk))\n this.logger.debug('Transactions signed successfully', { signedTxns })\n return signedTxns\n } catch (error: any) {\n this.logger.error('Error signing transactions:', error.message)\n throw error\n }\n }\n}\n","import { MnemonicAdapter } from './adapter'\nimport type { MnemonicOptions } from './adapter'\nimport type { WalletAdapterConfig, WalletFactoryOptions } from '@txnlab/use-wallet'\n\nexport const WALLET_ID = 'mnemonic' as const\n\nexport function mnemonic(options?: MnemonicOptions & WalletFactoryOptions): WalletAdapterConfig {\n const { metadata, ...adapterOptions } = options ?? {}\n return {\n id: WALLET_ID,\n metadata: { ...MnemonicAdapter.defaultMetadata, ...metadata },\n Adapter: MnemonicAdapter as unknown as WalletAdapterConfig['Adapter'],\n options:\n Object.keys(adapterOptions).length > 0\n ? (adapterOptions as unknown as Record<string, unknown>)\n : undefined,\n capabilities: { excludedNetworks: ['mainnet'] }\n }\n}\n\nexport { MnemonicAdapter }\nexport type { MnemonicOptions }\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@txnlab/use-wallet-mnemonic",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"provenance": true
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"algosdk": "3.6.0",
|
|
38
|
-
"tsdown": "0.
|
|
38
|
+
"tsdown": "0.23.0",
|
|
39
39
|
"typescript": "5.9.3",
|
|
40
|
-
"@txnlab/use-wallet": "5.0.
|
|
40
|
+
"@txnlab/use-wallet": "5.0.1"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"build": "tsdown",
|