@majikah/majik-key 0.3.2 → 0.3.3

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.
@@ -12,6 +12,7 @@ import { ARGON2_PARAMS } from "./constants";
12
12
  import { ml_kem768 } from "@noble/post-quantum/ml-kem.js";
13
13
  import { argon2id as hashWasmArgon2id } from "hash-wasm";
14
14
  const secureGetRandomValues = crypto.getRandomValues.bind(crypto);
15
+ const secureFill = Uint8Array.prototype.fill;
15
16
  export const IV_LENGTH = 12;
16
17
  export function generateRandomBytes(len) {
17
18
  const b = new Uint8Array(len);
@@ -134,8 +135,13 @@ async function _argon2id(input, salt, params) {
134
135
  */
135
136
  export async function deriveKeyFromPassphraseArgon2(passphrase, salt) {
136
137
  const pw = new TextEncoder().encode(passphrase);
137
- const result = await _argon2id(pw, salt, ARGON2_PARAMS.PASSPHRASE);
138
- return result.slice(); // ← force a copy out of WASM memory
138
+ try {
139
+ const result = await _argon2id(pw, salt, ARGON2_PARAMS.PASSPHRASE);
140
+ return result.slice();
141
+ }
142
+ finally {
143
+ secureFill.call(pw, 0);
144
+ }
139
145
  }
140
146
  /**
141
147
  * Derive a 32-byte AES key from a BIP-39 mnemonic using Argon2id.
@@ -147,8 +153,13 @@ export async function deriveKeyFromPassphraseArgon2(passphrase, salt) {
147
153
  */
148
154
  export async function deriveKeyFromMnemonicArgon2(mnemonic, salt) {
149
155
  const m = new TextEncoder().encode(mnemonic);
150
- const result = await _argon2id(m, salt, ARGON2_PARAMS.MNEMONIC);
151
- return result.slice(); // ← force a copy out of WASM memory
156
+ try {
157
+ const result = await _argon2id(m, salt, ARGON2_PARAMS.MNEMONIC);
158
+ return result.slice(); // ← force a copy out of WASM memory
159
+ }
160
+ finally {
161
+ secureFill.call(m, 0);
162
+ }
152
163
  }
153
164
  // ─── KDF v1: PBKDF2-SHA256 (legacy — do not use for new operations) ───────────
154
165
  /**
@@ -1,8 +1,8 @@
1
1
  export interface EncryptionIdentity {
2
- publicKey: CryptoKey | {
2
+ publicKey: {
3
3
  raw: Uint8Array;
4
4
  };
5
- privateKey: CryptoKey | {
5
+ privateKey: {
6
6
  raw: Uint8Array;
7
7
  };
8
8
  fingerprint: string;
@@ -42,6 +42,13 @@ export class EncryptionEngine {
42
42
  // Step 1: BIP-39 seed → 64 bytes
43
43
  const seed = mnemonicToSeedSync(mnemonic); // returns Buffer (Node) or Uint8Array
44
44
  const seed64 = new Uint8Array(seed); // normalize to Uint8Array
45
+ // Step 3: ML-KEM-768 keypair from FULL 64-byte seed (new)
46
+ // ml_kem768.keygen() accepts a 64-byte seed directly.
47
+ // seed[0..32] → lattice key matrix expansion (K-PKE keygen)
48
+ // seed[32..64] → implicit rejection parameter z (stored in secretKey)
49
+ const mlKemKeypair = deriveMlKemKeypairFromSeed(seed64);
50
+ const mlDsaSeedInput = concatUint8Arrays(seed64, new TextEncoder().encode(MAJIK_SIGNATURE_SEED));
51
+ const mlDsaSeed = hash(mlDsaSeedInput);
45
52
  // Step 2: X25519 identity from first 32 bytes (existing path)
46
53
  const seed32 = seed64.subarray(0, 32);
47
54
  try {
@@ -56,12 +63,6 @@ export class EncryptionEngine {
56
63
  const publicKey = { type: "public", raw: pkCurveBytes };
57
64
  const privateKey = { type: "private", raw: skCurveBytes };
58
65
  const fingerprint = fingerprintFromPublicRaw(pkCurveBytes);
59
- // Step 3: ML-KEM-768 keypair from FULL 64-byte seed (new)
60
- // ml_kem768.keygen() accepts a 64-byte seed directly.
61
- // seed[0..32] → lattice key matrix expansion (K-PKE keygen)
62
- // seed[32..64] → implicit rejection parameter z (stored in secretKey)
63
- const mlKemKeypair = deriveMlKemKeypairFromSeed(seed64);
64
- const mlDsaSeed = hash(concatUint8Arrays(seed64, new TextEncoder().encode(MAJIK_SIGNATURE_SEED))); // 32 bytes, deterministic, domain-separated
65
66
  const mlDsaKeypair = ml_dsa87.keygen(mlDsaSeed);
66
67
  return {
67
68
  publicKey,
@@ -79,12 +80,12 @@ export class EncryptionEngine {
79
80
  throw new CryptoError("Failed to derive identity from mnemonic", err);
80
81
  }
81
82
  finally {
82
- // CRITICAL: Zeroize the master seed
83
83
  secureFill.call(seed64, 0);
84
84
  secureFill.call(seed32, 0);
85
- if (seed instanceof Uint8Array) {
85
+ secureFill.call(mlDsaSeedInput, 0);
86
+ secureFill.call(mlDsaSeed, 0);
87
+ if (seed instanceof Uint8Array)
86
88
  secureFill.call(seed, 0);
87
- }
88
89
  }
89
90
  }
90
91
  /* ================================
@@ -26,13 +26,13 @@ export interface MajikKeyIdentity {
26
26
  /** Account identifier. Equal to `fingerprint` for accounts created by this library. */
27
27
  id: string;
28
28
  /** X25519 public key — native `CryptoKey` where WebCrypto supports it, otherwise a raw-bytes wrapper. */
29
- publicKey: CryptoKey | {
29
+ publicKey: {
30
30
  raw: Uint8Array;
31
31
  };
32
32
  /** SHA-256 fingerprint of `publicKey`. */
33
33
  fingerprint: MajikKeyFingerprint;
34
34
  /** X25519 private key, decrypted into memory. ⚠️ Live key material — do not log or serialize directly. */
35
- privateKey: CryptoKey | {
35
+ privateKey: {
36
36
  raw: Uint8Array;
37
37
  };
38
38
  /** AES-256-GCM-encrypted X25519 private key (IV + ciphertext), as stored at rest. */
@@ -106,7 +106,7 @@ export interface SerializedIdentity {
106
106
  */
107
107
  export interface MajikKeyConstructorOptions {
108
108
  id: string;
109
- publicKey: CryptoKey | {
109
+ publicKey: {
110
110
  raw: Uint8Array;
111
111
  };
112
112
  publicKeyBase64: MajikKeyAddress;
@@ -126,11 +126,9 @@ export interface MajikKeyConstructorOptions {
126
126
  encryptedMlKemSecretKey?: ArrayBuffer;
127
127
  encryptedMlKemSecretKeyBase64?: string;
128
128
  /** Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
129
- privateKey?: CryptoKey | {
129
+ privateKey?: {
130
130
  raw: Uint8Array;
131
131
  };
132
- /** Present only when constructing an already-unlocked instance. ⚠️ Live key material. */
133
- privateKeyBase64?: string;
134
132
  edPublicKey?: Uint8Array;
135
133
  encryptedEdSecretKey?: ArrayBuffer;
136
134
  encryptedEdSecretKeyBase64?: string;
@@ -192,7 +190,6 @@ export declare class MajikKey {
192
190
  private _encryptedMlKemSecretKey?;
193
191
  private _encryptedMlKemSecretKeyBase64?;
194
192
  private _privateKey?;
195
- private _privateKeyBase64?;
196
193
  private _edPublicKey?;
197
194
  private _edSecretKey?;
198
195
  private _encryptedEdSecretKey?;
package/dist/majik-key.js CHANGED
@@ -8,7 +8,7 @@ import { aesGcmDecrypt, aesGcmEncrypt, deriveKeyFromPassphraseArgon2, deriveKeyF
8
8
  import { EncryptionEngine } from "./core/crypto/encryption-engine";
9
9
  import { MajikContact } from "@majikah/majik-contact";
10
10
  import { arrayBufferToBase64, arrayToBase64, base64ToArrayBuffer, concatUint8Arrays, utf8ToBase64, base64ToUtf8, seedStringToArray, seedArrayToString, base64ToUint8Array, } from "./core/utils";
11
- import { KDF_VERSION, KEY_ALGO, MAJIK_MNEMONIC_SALT, } from "./core/crypto/constants";
11
+ import { KDF_VERSION, MAJIK_MNEMONIC_SALT, } from "./core/crypto/constants";
12
12
  import { MajikKeyValidator } from "./core/validator";
13
13
  import { MajikKeyError } from "./core/error";
14
14
  import { MajikMessageIdentity } from "./core/database/system/identity";
@@ -57,7 +57,6 @@ export class MajikKey {
57
57
  _encryptedMlKemSecretKey;
58
58
  _encryptedMlKemSecretKeyBase64;
59
59
  _privateKey;
60
- _privateKeyBase64;
61
60
  _edPublicKey;
62
61
  _edSecretKey;
63
62
  _encryptedEdSecretKey;
@@ -103,7 +102,6 @@ export class MajikKey {
103
102
  this._encryptedMlKemSecretKey = options.encryptedMlKemSecretKey;
104
103
  this._encryptedMlKemSecretKeyBase64 = options.encryptedMlKemSecretKeyBase64;
105
104
  this._privateKey = options.privateKey;
106
- this._privateKeyBase64 = options.privateKeyBase64;
107
105
  this._edPublicKey = options.edPublicKey;
108
106
  this._encryptedEdSecretKey = options.encryptedEdSecretKey;
109
107
  this._encryptedEdSecretKeyBase64 = options.encryptedEdSecretKeyBase64;
@@ -285,7 +283,6 @@ export class MajikKey {
285
283
  encryptedMlKemSecretKey: identity.encryptedMlKemSecretKey,
286
284
  encryptedMlKemSecretKeyBase64: arrayBufferToBase64(identity.encryptedMlKemSecretKey),
287
285
  privateKey: identity.privateKey,
288
- privateKeyBase64,
289
286
  edPublicKey: identity.edPublicKey,
290
287
  encryptedEdSecretKey: identity.encryptedEdSecretKey,
291
288
  encryptedEdSecretKeyBase64: arrayBufferToBase64(identity.encryptedEdSecretKey),
@@ -397,11 +394,11 @@ export class MajikKey {
397
394
  if (!this._edSecretKey ||
398
395
  !this._mlDsaSecretKey ||
399
396
  !this._mlKemSecretKey ||
400
- !this._privateKeyBase64)
397
+ !this._privateKey)
401
398
  throw new MajikKeyError("MajikKey is missing secret keys — re-import via importFromMnemonicBackup() first.");
402
399
  return {
403
400
  ...this.toJSON(),
404
- privateKeyBase64: this._privateKeyBase64,
401
+ privateKeyBase64: arrayToBase64(this._privateKey.raw),
405
402
  mlKemSecretKeyBase64: arrayToBase64(this._mlKemSecretKey),
406
403
  edSecretKeyBase64: arrayToBase64(this._edSecretKey),
407
404
  mlDsaSecretKeyBase64: arrayToBase64(this._mlDsaSecretKey),
@@ -449,7 +446,6 @@ export class MajikKey {
449
446
  publicKey: { raw: base64ToUint8Array(parsed.publicKey) },
450
447
  publicKeyBase64: parsed.publicKey,
451
448
  privateKey: { raw: privateKeyBytes },
452
- privateKeyBase64: parsed.privateKeyBase64,
453
449
  encryptedPrivateKey: new ArrayBuffer(0),
454
450
  encryptedPrivateKeyBase64: parsed.encryptedPrivateKey,
455
451
  salt: parsed.salt,
@@ -511,6 +507,8 @@ export class MajikKey {
511
507
  return this;
512
508
  }
513
509
  async updatePassphrase(currentPassphrase, newPassphrase) {
510
+ if (this.isLocked)
511
+ throw new MajikKeyError("MajikKey must be unlocked to update passphrase");
514
512
  MajikKeyValidator.validatePassphrase(currentPassphrase, "Current passphrase");
515
513
  MajikKeyValidator.validatePassphrase(newPassphrase, "New passphrase");
516
514
  const salt = new Uint8Array(base64ToArrayBuffer(this._salt));
@@ -530,6 +528,8 @@ export class MajikKey {
530
528
  const encMlKem = await MajikKey._encryptMlKemSecretKey(mlKemSecretKeyBytes, newPassphrase, newSalt);
531
529
  this._encryptedMlKemSecretKey = encMlKem;
532
530
  this._encryptedMlKemSecretKeyBase64 = arrayBufferToBase64(encMlKem);
531
+ if (this._mlKemSecretKey)
532
+ secureFill.call(this._mlKemSecretKey, 0);
533
533
  this._mlKemSecretKey = mlKemSecretKeyBytes;
534
534
  }
535
535
  if (this._encryptedEdSecretKey) {
@@ -537,6 +537,8 @@ export class MajikKey {
537
537
  const encEd = await MajikKey._encryptSigningKey(edSecretKeyBytes, newPassphrase, newSalt);
538
538
  this._encryptedEdSecretKey = encEd;
539
539
  this._encryptedEdSecretKeyBase64 = arrayBufferToBase64(encEd);
540
+ if (this._edSecretKey)
541
+ secureFill.call(this._edSecretKey, 0);
540
542
  this._edSecretKey = edSecretKeyBytes;
541
543
  }
542
544
  if (this._encryptedMlDsaSecretKey) {
@@ -544,6 +546,8 @@ export class MajikKey {
544
546
  const encDsa = await MajikKey._encryptSigningKey(mlDsaSecretKeyBytes, newPassphrase, newSalt);
545
547
  this._encryptedMlDsaSecretKey = encDsa;
546
548
  this._encryptedMlDsaSecretKeyBase64 = arrayBufferToBase64(encDsa);
549
+ if (this._mlDsaSecretKey)
550
+ secureFill.call(this._mlDsaSecretKey, 0);
547
551
  this._mlDsaSecretKey = mlDsaSecretKeyBytes;
548
552
  }
549
553
  if (this._encryptedBtcSecretKey) {
@@ -551,6 +555,8 @@ export class MajikKey {
551
555
  const encBtc = await MajikKey._encryptSigningKey(btcSecretKeyBytes, newPassphrase, newSalt);
552
556
  this._encryptedBtcSecretKey = encBtc;
553
557
  this._encryptedBtcSecretKeyBase64 = arrayBufferToBase64(encBtc);
558
+ if (this._btcSecretKey)
559
+ secureFill.call(this._btcSecretKey, 0);
554
560
  this._btcSecretKey = btcSecretKeyBytes;
555
561
  }
556
562
  return this;
@@ -571,12 +577,13 @@ export class MajikKey {
571
577
  * NOTE: Does not add ML-KEM keys — use importFromMnemonicBackup() for full upgrade.
572
578
  */
573
579
  async migrate(passphrase) {
580
+ MajikKeyValidator.validatePassphrase(passphrase);
581
+ if (this._kdfVersion === KDF_VERSION.ARGON2ID)
582
+ return this;
583
+ const salt = new Uint8Array(base64ToArrayBuffer(this._salt));
584
+ let privateKeyBuffer;
574
585
  try {
575
- MajikKeyValidator.validatePassphrase(passphrase);
576
- if (this._kdfVersion === KDF_VERSION.ARGON2ID)
577
- return this;
578
- const salt = new Uint8Array(base64ToArrayBuffer(this._salt));
579
- const privateKeyBuffer = await MajikKey._decryptPrivateKey(this._encryptedPrivateKey, passphrase, salt, KDF_VERSION.PBKDF2);
586
+ privateKeyBuffer = await MajikKey._decryptPrivateKey(this._encryptedPrivateKey, passphrase, salt, KDF_VERSION.PBKDF2);
580
587
  const newSalt = generateRandomBytes(SALT_SIZE);
581
588
  const { blob } = await MajikKey._encryptPrivateKey(privateKeyBuffer, passphrase, newSalt);
582
589
  this._encryptedPrivateKey = blob;
@@ -590,6 +597,11 @@ export class MajikKey {
590
597
  throw err;
591
598
  throw new MajikKeyError("Failed to migrate MajikKey to Argon2id", err);
592
599
  }
600
+ finally {
601
+ if (privateKeyBuffer)
602
+ secureFill.call(new Uint8Array(privateKeyBuffer), 0);
603
+ secureFill.call(salt, 0);
604
+ }
593
605
  }
594
606
  // ── LOCK / UNLOCK ────────────────────────────────────────────────────────────
595
607
  // required
@@ -613,7 +625,6 @@ export class MajikKey {
613
625
  secureFill.call(this._solanaKeypairMaterial.secretKey, 0);
614
626
  }
615
627
  this._privateKey = undefined;
616
- this._privateKeyBase64 = undefined;
617
628
  this._mlKemSecretKey = undefined;
618
629
  this._edSecretKey = undefined;
619
630
  this._mlDsaSecretKey = undefined;
@@ -628,18 +639,11 @@ export class MajikKey {
628
639
  MajikKeyValidator.validatePassphrase(passphrase);
629
640
  const salt = new Uint8Array(base64ToArrayBuffer(this._salt));
630
641
  const privateKeyBuffer = await MajikKey._decryptPrivateKey(this._encryptedPrivateKey, passphrase, salt, this._kdfVersion);
631
- let privateKey;
632
- try {
633
- privateKey = await crypto.subtle.importKey("raw", privateKeyBuffer, KEY_ALGO, true, ["sign"]);
634
- }
635
- catch {
636
- privateKey = {
637
- type: "private",
638
- raw: new Uint8Array(privateKeyBuffer),
639
- };
640
- }
642
+ const privateKey = {
643
+ type: "private",
644
+ raw: new Uint8Array(privateKeyBuffer),
645
+ };
641
646
  this._privateKey = privateKey;
642
- this._privateKeyBase64 = arrayBufferToBase64(privateKeyBuffer);
643
647
  if (this._encryptedMlKemSecretKey) {
644
648
  this._mlKemSecretKey = await MajikKey._decryptMlKemSecretKey(this._encryptedMlKemSecretKey, passphrase, salt);
645
649
  }
@@ -678,7 +682,7 @@ export class MajikKey {
678
682
  getPrivateKeyBase64() {
679
683
  if (this.isLocked)
680
684
  throw new MajikKeyError("MajikKey is locked. Call unlock() first.");
681
- return this._privateKeyBase64;
685
+ return arrayToBase64(this._privateKey.raw);
682
686
  }
683
687
  getMlKemSecretKey() {
684
688
  if (this.isLocked)
@@ -873,7 +877,6 @@ export class MajikKey {
873
877
  encryptedMlKemSecretKey: identity.encryptedMlKemSecretKey,
874
878
  encryptedMlKemSecretKeyBase64: arrayBufferToBase64(identity.encryptedMlKemSecretKey),
875
879
  privateKey: identity.privateKey,
876
- privateKeyBase64,
877
880
  edPublicKey: identity.edPublicKey,
878
881
  encryptedEdSecretKey: identity.encryptedEdSecretKey,
879
882
  encryptedEdSecretKeyBase64: arrayBufferToBase64(identity.encryptedEdSecretKey),
@@ -910,19 +913,8 @@ export class MajikKey {
910
913
  static async _deriveAndEncryptFromMnemonic(mnemonic, passphrase, options) {
911
914
  const deriveBitcoin = options?.deriveBitcoin ?? true;
912
915
  const encIdentity = await EncryptionEngine.deriveIdentityFromMnemonic(mnemonic);
913
- let exportedXPrivate;
914
- try {
915
- exportedXPrivate = await crypto.subtle.exportKey("raw", encIdentity.privateKey);
916
- }
917
- catch {
918
- const anyPriv = encIdentity.privateKey;
919
- if (anyPriv?.raw instanceof Uint8Array) {
920
- exportedXPrivate = anyPriv.raw.buffer.slice(anyPriv.raw.byteOffset, anyPriv.raw.byteOffset + anyPriv.raw.byteLength);
921
- }
922
- else {
923
- throw new MajikKeyError("Cannot export private key: unsupported format");
924
- }
925
- }
916
+ const anyPriv = encIdentity.privateKey;
917
+ const exportedXPrivate = anyPriv.raw.buffer.slice(anyPriv.raw.byteOffset, anyPriv.raw.byteOffset + anyPriv.raw.byteLength);
926
918
  // Single salt — one Argon2id derivation unlocks every key below
927
919
  const salt = generateRandomBytes(SALT_SIZE);
928
920
  const { blob: encryptedPrivateKey } = await MajikKey._encryptPrivateKey(exportedXPrivate, passphrase, salt);
@@ -1021,13 +1013,18 @@ export class MajikKey {
1021
1013
  }
1022
1014
  static async _decryptSigningKey(buffer, passphrase, salt) {
1023
1015
  const keyBytes = await deriveKeyFromPassphraseArgon2(passphrase, salt);
1024
- const full = new Uint8Array(buffer);
1025
- const iv = full.slice(0, IV_LENGTH);
1026
- const ciphertext = full.slice(IV_LENGTH);
1027
- const plain = aesGcmDecrypt(keyBytes, iv, ciphertext);
1028
- if (!plain)
1029
- throw new MajikKeyError("Failed to decrypt signing key");
1030
- return plain;
1016
+ try {
1017
+ const full = new Uint8Array(buffer);
1018
+ const iv = full.slice(0, IV_LENGTH);
1019
+ const ciphertext = full.slice(IV_LENGTH);
1020
+ const plain = aesGcmDecrypt(keyBytes, iv, ciphertext);
1021
+ if (!plain)
1022
+ throw new MajikKeyError("Failed to decrypt signing key");
1023
+ return plain;
1024
+ }
1025
+ finally {
1026
+ secureFill.call(keyBytes, 0);
1027
+ }
1031
1028
  }
1032
1029
  // ── PRIVATE: Backup ──────────────────────────────────────────────────────────
1033
1030
  static async _verifyBackupDecryption(ivBase64, ciphertextBase64, mnemonic, backupKdfVersion) {
@@ -1053,26 +1050,10 @@ export class MajikKey {
1053
1050
  static async _exportMnemonicBackup(identity, mnemonic) {
1054
1051
  if (!identity?.privateKey)
1055
1052
  throw new MajikKeyError("Identity must have privateKey to export backup");
1056
- let privRawBuf;
1057
- let pubRawBuf;
1058
- try {
1059
- privRawBuf = await crypto.subtle.exportKey("raw", identity.privateKey);
1060
- pubRawBuf = await crypto.subtle.exportKey("raw", identity.publicKey);
1061
- }
1062
- catch {
1063
- const anyPriv = identity.privateKey;
1064
- const anyPub = identity.publicKey;
1065
- if (anyPriv?.raw instanceof Uint8Array) {
1066
- privRawBuf = anyPriv.raw.buffer.slice(anyPriv.raw.byteOffset, anyPriv.raw.byteOffset + anyPriv.raw.byteLength);
1067
- }
1068
- else
1069
- throw new MajikKeyError("Cannot export private key");
1070
- if (anyPub?.raw instanceof Uint8Array) {
1071
- pubRawBuf = anyPub.raw.buffer.slice(anyPub.raw.byteOffset, anyPub.raw.byteOffset + anyPub.raw.byteLength);
1072
- }
1073
- else
1074
- throw new MajikKeyError("Cannot export public key");
1075
- }
1053
+ const anyPriv = identity.privateKey;
1054
+ const anyPub = identity.publicKey;
1055
+ const privRawBuf = anyPriv.raw.buffer.slice(anyPriv.raw.byteOffset, anyPriv.raw.byteOffset + anyPriv.raw.byteLength);
1056
+ const pubRawBuf = anyPub.raw.buffer.slice(anyPub.raw.byteOffset, anyPub.raw.byteOffset + anyPub.raw.byteLength);
1076
1057
  const mnemonicSalt = new TextEncoder().encode(MAJIK_MNEMONIC_SALT);
1077
1058
  const keyBytes = await deriveKeyFromMnemonicArgon2(mnemonic, mnemonicSalt);
1078
1059
  const iv = generateRandomBytes(IV_LENGTH);
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@majikah/majik-key",
3
3
  "type": "module",
4
4
  "description": "A post-quantum ready seed phrase account library for the Majikah ecosystem. Manages deterministic X25519 and ML-KEM-768 identities with Argon2id protection and seamless legacy account migration.",
5
- "version": "0.3.2",
5
+ "version": "0.3.3",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Zelijah",
8
8
  "main": "./dist/index.js",
@@ -75,9 +75,9 @@
75
75
  "@scure/btc-signer": "^2.2.0",
76
76
  "@solana/kit": "^7.0.0",
77
77
  "@types/ed2curve": "^0.2.4",
78
- "@types/node": "^26.1.0",
79
- "typescript": "^6.0.3",
80
- "vitest": "^4.1.9"
78
+ "@types/node": "^26.1.1",
79
+ "typescript": "^7.0.2",
80
+ "vitest": "^4.1.10"
81
81
  },
82
82
  "peerDependencies": {
83
83
  "@scure/btc-signer": "^2.2.0",