@beclab/olaresid 0.1.4 → 0.1.6

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.
Files changed (52) hide show
  1. package/dist/business/index.d.ts +3 -3
  2. package/dist/business/index.d.ts.map +1 -1
  3. package/dist/business/index.js +49 -64
  4. package/dist/business/index.js.map +1 -1
  5. package/dist/cli.js +3 -3
  6. package/dist/cli.js.map +1 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +6 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/utils/crypto-utils.d.ts +32 -4
  12. package/dist/utils/crypto-utils.d.ts.map +1 -1
  13. package/dist/utils/crypto-utils.js +117 -30
  14. package/dist/utils/crypto-utils.js.map +1 -1
  15. package/examples/crypto-utilities.ts +3 -3
  16. package/examples/ed25519-jwk.ts +1 -1
  17. package/examples/encoding-utils.ts +96 -0
  18. package/examples/frontend-demo/.dockerignore +40 -0
  19. package/examples/frontend-demo/index.html +13 -0
  20. package/examples/frontend-demo/package-lock.json +5304 -0
  21. package/examples/frontend-demo/package.json +32 -0
  22. package/examples/frontend-demo/src/App.vue +1156 -0
  23. package/examples/frontend-demo/src/main.ts +5 -0
  24. package/examples/frontend-demo/src/style.css +323 -0
  25. package/examples/frontend-demo/tsconfig.json +24 -0
  26. package/examples/frontend-demo/webpack.config.js +86 -0
  27. package/examples/generate-mnemonic.ts +3 -3
  28. package/examples/register-subdomain.ts +4 -3
  29. package/examples/transfer-domain.ts +1 -1
  30. package/examples/wallet-management.ts +8 -8
  31. package/package.json +1 -3
  32. package/src/business/index.ts +46 -58
  33. package/src/cli.ts +3 -3
  34. package/src/index.ts +6 -1
  35. package/src/utils/crypto-utils.ts +134 -32
  36. package/examples/quasar-demo/.eslintrc.js +0 -23
  37. package/examples/quasar-demo/.quasar/app.js +0 -43
  38. package/examples/quasar-demo/.quasar/client-entry.js +0 -38
  39. package/examples/quasar-demo/.quasar/client-prefetch.js +0 -130
  40. package/examples/quasar-demo/.quasar/quasar-user-options.js +0 -16
  41. package/examples/quasar-demo/README.md +0 -49
  42. package/examples/quasar-demo/index.html +0 -11
  43. package/examples/quasar-demo/package-lock.json +0 -6407
  44. package/examples/quasar-demo/package.json +0 -36
  45. package/examples/quasar-demo/quasar.config.js +0 -73
  46. package/examples/quasar-demo/src/App.vue +0 -13
  47. package/examples/quasar-demo/src/css/app.scss +0 -1
  48. package/examples/quasar-demo/src/layouts/MainLayout.vue +0 -21
  49. package/examples/quasar-demo/src/pages/IndexPage.vue +0 -905
  50. package/examples/quasar-demo/src/router/index.ts +0 -25
  51. package/examples/quasar-demo/src/router/routes.ts +0 -11
  52. package/examples/quasar-demo/tsconfig.json +0 -28
@@ -4,6 +4,12 @@ import { parseContractError } from '../utils/error-parser';
4
4
  import { TagContext } from './tag-context';
5
5
  import { TagTypeBuilder } from '../utils/tag-type-builder';
6
6
  import { normalizeToDomain } from '../utils/olares-id';
7
+ import {
8
+ base64ToUint8Array,
9
+ uint8ArrayToHex,
10
+ hexToUint8Array,
11
+ uint8ArrayToBase64
12
+ } from '../utils/crypto-utils';
7
13
 
8
14
  export interface TransactionResult<T = any> {
9
15
  // Basic transaction information
@@ -48,7 +54,11 @@ export {
48
54
  getDIDFromMnemonic,
49
55
  generateDIDKeyData,
50
56
  deriveDIDFromMnemonic,
51
- getEd25519JwkFromMnemonic
57
+ getEd25519JwkFromMnemonic,
58
+ base64ToUint8Array,
59
+ uint8ArrayToHex,
60
+ hexToUint8Array,
61
+ uint8ArrayToBase64
52
62
  } from '../utils/crypto-utils';
53
63
  export type { RSAPublicKeyData, DIDKeyData } from '../utils/crypto-utils';
54
64
 
@@ -180,7 +190,7 @@ export class DomainContext {
180
190
  * ```typescript
181
191
  * // For parent domain "parent.com", register subdomain "child"
182
192
  * const parentDomain = olaresId.domain('parent.com');
183
- * const mnemonic = generateMnemonic(12);
193
+ * const mnemonic = await generateMnemonic(12);
184
194
  *
185
195
  * const result = await parentDomain.registerSubdomain('child', mnemonic);
186
196
  * // This will register "child.parent.com"
@@ -266,7 +276,7 @@ export class DomainContext {
266
276
  *
267
277
  * @example
268
278
  * ```typescript
269
- * const mnemonic = generateMnemonic(12);
279
+ * const mnemonic = await generateMnemonic(12);
270
280
  * const result = await domain.transfer(mnemonic);
271
281
  * if (result.success) {
272
282
  * console.log('Domain transferred!');
@@ -846,18 +856,22 @@ export class DomainContext {
846
856
  const { Keypair } = await import('@solana/web3.js');
847
857
  const nacl = await import('tweetnacl');
848
858
  const { decodeUTF8 } = await import('tweetnacl-util');
859
+ const { base58btc } = await import('multiformats/bases/base58');
849
860
 
850
861
  // Parse Solana private key (support both base58 and base64)
851
862
  let solanaWallet: any;
852
863
  try {
853
864
  // Try base58 first (most common format for Phantom)
854
- const bs58 = await import('bs58');
855
- const secretKey = bs58.default.decode(solanaPrivateKey);
865
+ // Solana uses plain base58, but multiformats requires 'z' prefix for multibase
866
+ const base58Key = solanaPrivateKey.startsWith('z')
867
+ ? solanaPrivateKey
868
+ : 'z' + solanaPrivateKey;
869
+ const secretKey = base58btc.decode(base58Key);
856
870
  solanaWallet = Keypair.fromSecretKey(secretKey);
857
871
  } catch {
858
872
  // Try base64
859
873
  try {
860
- const secretKey = Buffer.from(solanaPrivateKey, 'base64');
874
+ const secretKey = base64ToUint8Array(solanaPrivateKey);
861
875
  solanaWallet = Keypair.fromSecretKey(secretKey);
862
876
  } catch {
863
877
  // Try as JSON array
@@ -868,9 +882,9 @@ export class DomainContext {
868
882
  }
869
883
  }
870
884
 
871
- // Get Solana address as bytes32
885
+ // Get Solana address as bytes32 (cross-platform)
872
886
  const solanaAddressBytes =
873
- '0x' + solanaWallet.publicKey.toBuffer().toString('hex');
887
+ '0x' + uint8ArrayToHex(solanaWallet.publicKey.toBytes());
874
888
 
875
889
  // Get current timestamp
876
890
  const signAt = Math.floor(Date.now() / 1000) - 30 * 60; // 30 minutes ago
@@ -930,8 +944,8 @@ export class DomainContext {
930
944
  decodeUTF8(solanaMsg),
931
945
  solanaWallet.secretKey
932
946
  );
933
- const sigFromAuthAddrHex =
934
- '0x' + Buffer.from(sigFromAuthAddr).toString('hex');
947
+ // Convert signature to hex (cross-platform)
948
+ const sigFromAuthAddrHex = '0x' + uint8ArrayToHex(sigFromAuthAddr);
935
949
 
936
950
  // Call contract
937
951
  const tx = await rootTagger.updateSolanaWallet(
@@ -979,18 +993,22 @@ export class DomainContext {
979
993
  try {
980
994
  // Import Solana libraries dynamically
981
995
  const { Keypair } = await import('@solana/web3.js');
996
+ const { base58btc } = await import('multiformats/bases/base58');
982
997
 
983
998
  // Parse Solana private key
984
999
  let solanaWallet: any;
985
1000
  try {
986
1001
  // Try base58 first
987
- const bs58 = await import('bs58');
988
- const secretKey = bs58.default.decode(solanaPrivateKey);
1002
+ // Solana uses plain base58, but multiformats requires 'z' prefix for multibase
1003
+ const base58Key = solanaPrivateKey.startsWith('z')
1004
+ ? solanaPrivateKey
1005
+ : 'z' + solanaPrivateKey;
1006
+ const secretKey = base58btc.decode(base58Key);
989
1007
  solanaWallet = Keypair.fromSecretKey(secretKey);
990
1008
  } catch {
991
1009
  // Try base64
992
1010
  try {
993
- const secretKey = Buffer.from(solanaPrivateKey, 'base64');
1011
+ const secretKey = base64ToUint8Array(solanaPrivateKey);
994
1012
  solanaWallet = Keypair.fromSecretKey(secretKey);
995
1013
  } catch {
996
1014
  // Try as JSON array
@@ -1001,9 +1019,9 @@ export class DomainContext {
1001
1019
  }
1002
1020
  }
1003
1021
 
1004
- // Get Solana address as bytes32
1022
+ // Get Solana address as bytes32 (cross-platform)
1005
1023
  const solanaAddressBytes =
1006
- '0x' + solanaWallet.publicKey.toBuffer().toString('hex');
1024
+ '0x' + uint8ArrayToHex(solanaWallet.publicKey.toBytes());
1007
1025
 
1008
1026
  // Get current timestamp
1009
1027
  const signAt = Math.floor(Date.now() / 1000) - 30 * 60; // 30 minutes ago
@@ -1104,11 +1122,8 @@ export class DomainContext {
1104
1122
  // Extract addresses from the result and convert to base58
1105
1123
  // Result is array of { algorithm, addr } where addr is bytes32
1106
1124
  return result.map((item: any) => {
1107
- // Remove 0x prefix and convert hex to buffer
1108
- const hexStr = item.addr.startsWith('0x')
1109
- ? item.addr.slice(2)
1110
- : item.addr;
1111
- const buffer = Buffer.from(hexStr, 'hex');
1125
+ // Convert hex to Uint8Array (cross-platform)
1126
+ const buffer = hexToUint8Array(item.addr);
1112
1127
  // Convert to Solana public key and then to base58
1113
1128
  return new PublicKey(buffer).toBase58();
1114
1129
  });
@@ -1423,26 +1438,16 @@ export function bytes4ToIpv4(bytes4Hex: string): string {
1423
1438
  */
1424
1439
  export function pemToDer(pem: string): string {
1425
1440
  // Remove PEM headers, footers, and whitespace
1426
- const base64 = pem
1441
+ const base64Str = pem
1427
1442
  .replace(/-----BEGIN.*?-----/g, '')
1428
1443
  .replace(/-----END.*?-----/g, '')
1429
1444
  .replace(/\s/g, '');
1430
1445
 
1431
- // Convert base64 to hex
1432
- let hexString: string;
1433
-
1434
- // Check if running in Node.js or browser
1435
- if (typeof Buffer !== 'undefined') {
1436
- // Node.js environment
1437
- const derBuffer = Buffer.from(base64, 'base64');
1438
- hexString = derBuffer.toString('hex');
1439
- } else {
1440
- // Browser environment
1441
- const binaryString = atob(base64);
1442
- hexString = Array.from(binaryString, (char) =>
1443
- char.charCodeAt(0).toString(16).padStart(2, '0')
1444
- ).join('');
1445
- }
1446
+ // Convert base64 to Uint8Array using cross-platform method
1447
+ const derBuffer = base64ToUint8Array(base64Str);
1448
+
1449
+ // Convert to hex string
1450
+ const hexString = uint8ArrayToHex(derBuffer);
1446
1451
 
1447
1452
  // Convert to hex string with 0x prefix
1448
1453
  return '0x' + hexString;
@@ -1457,31 +1462,14 @@ export function derToPem(derHex: string): string {
1457
1462
  // Remove '0x' prefix if present
1458
1463
  const hexString = derHex.startsWith('0x') ? derHex.slice(2) : derHex;
1459
1464
 
1460
- // Convert hex to base64
1461
- let base64: string;
1462
-
1463
- // Check if running in Node.js or browser
1464
- if (typeof Buffer !== 'undefined') {
1465
- // Node.js environment
1466
- const derBuffer = Buffer.from(hexString, 'hex');
1467
- base64 = derBuffer.toString('base64');
1468
- } else {
1469
- // Browser environment
1470
- // Convert hex string to byte array
1471
- const bytes = new Uint8Array(hexString.length / 2);
1472
- for (let i = 0; i < hexString.length; i += 2) {
1473
- bytes[i / 2] = parseInt(hexString.substr(i, 2), 16);
1474
- }
1475
- // Convert byte array to binary string
1476
- const binaryString = String.fromCharCode(...bytes);
1477
- // Convert to base64
1478
- base64 = btoa(binaryString);
1479
- }
1465
+ // Convert hex to base64 using cross-platform methods
1466
+ const bytes = hexToUint8Array(hexString);
1467
+ const base64Str = uint8ArrayToBase64(bytes);
1480
1468
 
1481
1469
  // Split base64 into 64-character lines for PEM format
1482
1470
  const lines: string[] = [];
1483
- for (let i = 0; i < base64.length; i += 64) {
1484
- lines.push(base64.slice(i, i + 64));
1471
+ for (let i = 0; i < base64Str.length; i += 64) {
1472
+ lines.push(base64Str.slice(i, i + 64));
1485
1473
  }
1486
1474
 
1487
1475
  // Construct PEM format with headers and footers
package/src/cli.ts CHANGED
@@ -1014,7 +1014,7 @@ async function registerSubdomain(
1014
1014
  );
1015
1015
  process.exit(1);
1016
1016
  }
1017
- mnemonic = generateMnemonic(wordCount);
1017
+ mnemonic = await generateMnemonic(wordCount);
1018
1018
 
1019
1019
  // Save mnemonic to file
1020
1020
  const mnemonicFile = './subdomain-mnemonic.txt';
@@ -1141,7 +1141,7 @@ async function transferDomain(
1141
1141
  );
1142
1142
  process.exit(1);
1143
1143
  }
1144
- mnemonic = generateMnemonic(wordCount);
1144
+ mnemonic = await generateMnemonic(wordCount);
1145
1145
 
1146
1146
  // Save mnemonic to file
1147
1147
  const mnemonicFile = './transfer-new-owner-mnemonic.txt';
@@ -1228,7 +1228,7 @@ async function cryptoGenerate(options: CliOptions): Promise<void> {
1228
1228
  process.exit(1);
1229
1229
  }
1230
1230
 
1231
- const mnemonic = generateMnemonic(wordCount);
1231
+ const mnemonic = await generateMnemonic(wordCount);
1232
1232
 
1233
1233
  // Save mnemonic to file
1234
1234
  const outputFile = options.output || './mnemonic.txt';
package/src/index.ts CHANGED
@@ -38,7 +38,12 @@ export {
38
38
  getDIDFromMnemonic,
39
39
  generateDIDKeyData,
40
40
  deriveDIDFromMnemonic,
41
- getEd25519JwkFromMnemonic
41
+ getEd25519JwkFromMnemonic,
42
+ // Cross-platform encoding utilities
43
+ base64ToUint8Array,
44
+ uint8ArrayToHex,
45
+ hexToUint8Array,
46
+ uint8ArrayToBase64
42
47
  } from './business';
43
48
 
44
49
  type Domain = PackageDomain.Domain;
@@ -6,13 +6,13 @@
6
6
  * compatibility across the entire Olares ecosystem.
7
7
  */
8
8
 
9
- import * as bip39 from 'bip39';
10
9
  import * as varint from 'varint';
11
10
  import { base58btc } from 'multiformats/bases/base58';
12
11
  import { base64url } from 'multiformats/bases/base64';
13
12
 
14
13
  // Browser globals type declaration
15
14
  declare const window: any;
15
+ declare const atob: (input: string) => string;
16
16
  declare const btoa: (input: string) => string;
17
17
 
18
18
  export interface RSAPublicKeyData {
@@ -26,6 +26,61 @@ export interface DIDKeyData {
26
26
  mnemonic: string;
27
27
  }
28
28
 
29
+ // ============================================================================
30
+ // Cross-platform encoding utilities (Browser + Node.js compatible)
31
+ // ============================================================================
32
+
33
+ /**
34
+ * Convert base64 string to Uint8Array (cross-platform)
35
+ * Works in both browser and Node.js environments
36
+ * @param base64 base64 encoded string
37
+ * @returns Uint8Array
38
+ */
39
+ export function base64ToUint8Array(base64: string): Uint8Array {
40
+ const binaryString = atob(base64);
41
+ const bytes = new Uint8Array(binaryString.length);
42
+ for (let i = 0; i < binaryString.length; i++) {
43
+ bytes[i] = binaryString.charCodeAt(i);
44
+ }
45
+ return bytes;
46
+ }
47
+
48
+ /**
49
+ * Convert Uint8Array to hex string (cross-platform)
50
+ * @param bytes Uint8Array to convert
51
+ * @returns hex string without '0x' prefix
52
+ */
53
+ export function uint8ArrayToHex(bytes: Uint8Array): string {
54
+ return Array.from(bytes)
55
+ .map((b) => b.toString(16).padStart(2, '0'))
56
+ .join('');
57
+ }
58
+
59
+ /**
60
+ * Convert hex string to Uint8Array (cross-platform)
61
+ * @param hex hex string (with or without '0x' prefix)
62
+ * @returns Uint8Array
63
+ */
64
+ export function hexToUint8Array(hex: string): Uint8Array {
65
+ const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;
66
+ const bytes = new Uint8Array(cleanHex.length / 2);
67
+ for (let i = 0; i < cleanHex.length; i += 2) {
68
+ bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16);
69
+ }
70
+ return bytes;
71
+ }
72
+
73
+ /**
74
+ * Convert Uint8Array to base64 string (cross-platform)
75
+ * Works in both browser and Node.js environments
76
+ * @param bytes Uint8Array to convert
77
+ * @returns base64 encoded string
78
+ */
79
+ export function uint8ArrayToBase64(bytes: Uint8Array): string {
80
+ const binaryString = String.fromCharCode(...bytes);
81
+ return btoa(binaryString);
82
+ }
83
+
29
84
  // ============================================================================
30
85
  // Trust Wallet Core Management
31
86
  // ============================================================================
@@ -37,6 +92,7 @@ let loadingPromise: Promise<any> | null = null;
37
92
  /**
38
93
  * Load Trust Wallet Core (lazy loading)
39
94
  * Works in both Node.js and browser environments
95
+ * Handles different module export formats (CommonJS vs ESM)
40
96
  */
41
97
  async function loadWalletCore(): Promise<any> {
42
98
  // Return cached instance if already loaded
@@ -52,18 +108,33 @@ async function loadWalletCore(): Promise<any> {
52
108
  // Start loading
53
109
  loadingPromise = (async () => {
54
110
  try {
55
- // Check if running in browser or Node.js
56
- if (
57
- typeof window !== 'undefined' &&
58
- typeof require === 'undefined'
111
+ // Dynamic import works in both Node.js ESM and browser ESM
112
+ const WalletCoreModule = await import('@trustwallet/wallet-core');
113
+
114
+ // Handle different export formats (CommonJS vs ESM)
115
+ let initWasmFunc: any;
116
+ if (WalletCoreModule.initWasm) {
117
+ // ESM named export
118
+ initWasmFunc = WalletCoreModule.initWasm;
119
+ } else if (
120
+ WalletCoreModule.default &&
121
+ (WalletCoreModule.default as any).initWasm
59
122
  ) {
60
- // Browser environment with ES modules
61
- const { initWasm } = await import('@trustwallet/wallet-core');
62
- walletCore = await initWasm();
123
+ // ESM default export with initWasm
124
+ initWasmFunc = (WalletCoreModule.default as any).initWasm;
125
+ } else if (WalletCoreModule.default) {
126
+ // Default export is the function itself
127
+ initWasmFunc = WalletCoreModule.default;
128
+ } else {
129
+ // Module itself is the function
130
+ initWasmFunc = WalletCoreModule as any;
131
+ }
132
+
133
+ // Call the init function
134
+ if (typeof initWasmFunc === 'function') {
135
+ walletCore = await initWasmFunc();
63
136
  } else {
64
- // Node.js environment
65
- const { initWasm } = require('@trustwallet/wallet-core');
66
- walletCore = await initWasm();
137
+ throw new Error('initWasm is not a function');
67
138
  }
68
139
 
69
140
  walletCoreLoaded = true;
@@ -84,23 +155,38 @@ async function loadWalletCore(): Promise<any> {
84
155
  // multicodec code for Ed25519 keys (0xed)
85
156
  const ED25519_CODEC_ID = varint.encode(parseInt('0xed', 16));
86
157
 
158
+ /**
159
+ * Simple mnemonic validation (checks word count)
160
+ * @param mnemonic BIP39 mnemonic phrase
161
+ * @returns true if mnemonic has valid word count (12, 15, 18, 21, or 24 words)
162
+ */
163
+ function validateMnemonic(mnemonic: string): boolean {
164
+ const words = mnemonic.trim().split(/\s+/);
165
+ const validWordCounts = [12, 15, 18, 21, 24];
166
+ return validWordCounts.includes(words.length);
167
+ }
168
+
87
169
  // ============================================================================
88
170
  // Mnemonic and Key Derivation Functions
89
171
  // ============================================================================
90
172
 
91
173
  /**
92
- * Generate a random BIP39 mnemonic phrase
174
+ * Generate a random BIP39 mnemonic phrase using Trust Wallet Core
175
+ * Works in both Node.js and browser environments
176
+ *
93
177
  * @param wordCount Number of words (12, 15, 18, 21, or 24), default is 12
94
- * @returns A mnemonic phrase string
178
+ * @returns A promise that resolves to a mnemonic phrase string
95
179
  *
96
180
  * @example
97
181
  * ```typescript
98
- * const mnemonic = generateMnemonic(12);
182
+ * const mnemonic = await generateMnemonic(12);
99
183
  * console.log(mnemonic);
100
184
  * // Output: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
101
185
  * ```
102
186
  */
103
- export function generateMnemonic(wordCount: number = 12): string {
187
+ export async function generateMnemonic(
188
+ wordCount: number = 12
189
+ ): Promise<string> {
104
190
  // Convert word count to entropy bits
105
191
  // 12 words = 128 bits, 15 words = 160 bits, etc.
106
192
  const strengthMap: Record<number, number> = {
@@ -118,7 +204,14 @@ export function generateMnemonic(wordCount: number = 12): string {
118
204
  );
119
205
  }
120
206
 
121
- return bip39.generateMnemonic(strength);
207
+ // Ensure Wallet Core is loaded
208
+ const core = await loadWalletCore();
209
+ const { HDWallet } = core;
210
+
211
+ const wallet = HDWallet.create(strength, '');
212
+ const mnemonic = wallet.mnemonic();
213
+
214
+ return mnemonic;
122
215
  }
123
216
 
124
217
  /**
@@ -138,8 +231,10 @@ export async function getEthereumAddressFromMnemonic(
138
231
  mnemonic: string
139
232
  ): Promise<string> {
140
233
  // Validate mnemonic
141
- if (!bip39.validateMnemonic(mnemonic)) {
142
- throw new Error('Invalid mnemonic phrase');
234
+ if (!validateMnemonic(mnemonic)) {
235
+ throw new Error(
236
+ 'Invalid mnemonic phrase: must have 12, 15, 18, 21, or 24 words'
237
+ );
143
238
  }
144
239
 
145
240
  const core = await loadWalletCore();
@@ -167,8 +262,10 @@ export async function getEVMPrivateKeyFromMnemonic(
167
262
  mnemonic: string
168
263
  ): Promise<string> {
169
264
  // Validate mnemonic
170
- if (!bip39.validateMnemonic(mnemonic)) {
171
- throw new Error('Invalid mnemonic phrase');
265
+ if (!validateMnemonic(mnemonic)) {
266
+ throw new Error(
267
+ 'Invalid mnemonic phrase: must have 12, 15, 18, 21, or 24 words'
268
+ );
172
269
  }
173
270
 
174
271
  const core = await loadWalletCore();
@@ -179,9 +276,9 @@ export async function getEVMPrivateKeyFromMnemonic(
179
276
  // Get private key for Ethereum
180
277
  const privateKeyData = wallet.getKeyForCoin(CoinType.ethereum);
181
278
 
182
- // Convert to hex string with 0x prefix
183
- const privateKeyHex =
184
- '0x' + Buffer.from(privateKeyData.data()).toString('hex');
279
+ // Convert to hex string with 0x prefix (cross-platform)
280
+ const privateKeyBytes = new Uint8Array(privateKeyData.data());
281
+ const privateKeyHex = '0x' + uint8ArrayToHex(privateKeyBytes);
185
282
 
186
283
  return privateKeyHex;
187
284
  }
@@ -230,8 +327,10 @@ async function getID(mnemonic: string): Promise<string> {
230
327
  */
231
328
  export async function getDIDFromMnemonic(mnemonic: string): Promise<string> {
232
329
  // Validate mnemonic
233
- if (!bip39.validateMnemonic(mnemonic)) {
234
- throw new Error('Invalid mnemonic phrase');
330
+ if (!validateMnemonic(mnemonic)) {
331
+ throw new Error(
332
+ 'Invalid mnemonic phrase: must have 12, 15, 18, 21, or 24 words'
333
+ );
235
334
  }
236
335
 
237
336
  const id = await getID(mnemonic);
@@ -278,8 +377,10 @@ export async function getEd25519JwkFromMnemonic(mnemonic: string): Promise<{
278
377
  privateJwk: any;
279
378
  }> {
280
379
  // Validate mnemonic
281
- if (!bip39.validateMnemonic(mnemonic)) {
282
- throw new Error('Invalid mnemonic phrase');
380
+ if (!validateMnemonic(mnemonic)) {
381
+ throw new Error(
382
+ 'Invalid mnemonic phrase: must have 12, 15, 18, 21, or 24 words'
383
+ );
283
384
  }
284
385
 
285
386
  const core = await loadWalletCore();
@@ -300,7 +401,6 @@ export async function getEd25519JwkFromMnemonic(mnemonic: string): Promise<{
300
401
  idBytes.set(publicKeyBytes, ED25519_CODEC_ID.length);
301
402
  const id = base58btc.encode(idBytes);
302
403
  const did = `did:key:${id}`;
303
- const keyId = `${did}#${id}`;
304
404
 
305
405
  // Base64url encode the keys
306
406
  const x = base64url.baseEncode(publicKeyBytes);
@@ -312,7 +412,7 @@ export async function getEd25519JwkFromMnemonic(mnemonic: string): Promise<{
312
412
  crv: 'Ed25519', // Curve: Ed25519
313
413
  alg: 'EdDSA', // Algorithm: EdDSA
314
414
  use: 'sig', // Use: signature
315
- kid: keyId, // Key ID
415
+ kid: did, // DID
316
416
  x: x // Public key parameter
317
417
  };
318
418
 
@@ -343,8 +443,10 @@ export async function deriveDIDFromMnemonic(mnemonic: string): Promise<{
343
443
  did: string;
344
444
  }> {
345
445
  // Validate mnemonic once upfront
346
- if (!bip39.validateMnemonic(mnemonic)) {
347
- throw new Error('Invalid mnemonic phrase');
446
+ if (!validateMnemonic(mnemonic)) {
447
+ throw new Error(
448
+ 'Invalid mnemonic phrase: must have 12, 15, 18, 21, or 24 words'
449
+ );
348
450
  }
349
451
 
350
452
  // Derive both in parallel for better performance
@@ -373,7 +475,7 @@ export async function deriveDIDFromMnemonic(mnemonic: string): Promise<{
373
475
  export async function generateDIDKeyData(
374
476
  wordCount: number = 12
375
477
  ): Promise<DIDKeyData> {
376
- const mnemonic = generateMnemonic(wordCount);
478
+ const mnemonic = await generateMnemonic(wordCount);
377
479
  const { owner, did } = await deriveDIDFromMnemonic(mnemonic);
378
480
 
379
481
  return {
@@ -1,23 +0,0 @@
1
- module.exports = {
2
- root: true,
3
- parserOptions: {
4
- parser: '@typescript-eslint/parser',
5
- ecmaVersion: 2021
6
- },
7
- env: {
8
- browser: true,
9
- es2021: true,
10
- node: true
11
- },
12
- extends: [
13
- 'plugin:vue/vue3-essential',
14
- 'eslint:recommended',
15
- '@vue/typescript/recommended',
16
- 'prettier'
17
- ],
18
- plugins: ['vue', '@typescript-eslint'],
19
- rules: {
20
- '@typescript-eslint/no-explicit-any': 'off',
21
- '@typescript-eslint/no-unused-vars': 'warn'
22
- }
23
- };
@@ -1,43 +0,0 @@
1
- /* eslint-disable */
2
- /**
3
- * THIS FILE IS GENERATED AUTOMATICALLY.
4
- * DO NOT EDIT.
5
- *
6
- * You are probably looking on adding startup/initialization code.
7
- * Use "quasar new boot <name>" and add it there.
8
- * One boot file per concern. Then reference the file(s) in quasar.config.js > boot:
9
- * boot: ['file', ...] // do not add ".js" extension to it.
10
- *
11
- * Boot files are your "main.js"
12
- **/
13
-
14
- import { Quasar } from 'quasar';
15
- import { markRaw } from 'vue';
16
- import RootComponent from 'app/src/App.vue';
17
-
18
- import createRouter from 'app/src/router/index';
19
-
20
- export default async function (createAppFn, quasarUserOptions) {
21
- // Create the app instance.
22
- // Here we inject into it the Quasar UI, the router & possibly the store.
23
- const app = createAppFn(RootComponent);
24
-
25
- app.config.performance = true;
26
-
27
- app.use(Quasar, quasarUserOptions);
28
-
29
- const router = markRaw(
30
- typeof createRouter === 'function'
31
- ? await createRouter({})
32
- : createRouter
33
- );
34
-
35
- // Expose the app, the router and the store.
36
- // Note that we are not mounting the app here, since bootstrapping will be
37
- // different depending on whether we are in a browser or on the server.
38
- return {
39
- app,
40
-
41
- router
42
- };
43
- }
@@ -1,38 +0,0 @@
1
- /* eslint-disable */
2
- /**
3
- * THIS FILE IS GENERATED AUTOMATICALLY.
4
- * DO NOT EDIT.
5
- *
6
- * You are probably looking on adding startup/initialization code.
7
- * Use "quasar new boot <name>" and add it there.
8
- * One boot file per concern. Then reference the file(s) in quasar.config.js > boot:
9
- * boot: ['file', ...] // do not add ".js" extension to it.
10
- *
11
- * Boot files are your "main.js"
12
- **/
13
-
14
- import { createApp } from 'vue';
15
-
16
- import '@quasar/extras/roboto-font/roboto-font.css';
17
-
18
- import '@quasar/extras/material-icons/material-icons.css';
19
-
20
- // We load Quasar stylesheet file
21
- import 'quasar/dist/quasar.css';
22
-
23
- import 'src/css/app.scss';
24
-
25
- import createQuasarApp from './app.js';
26
- import quasarUserOptions from './quasar-user-options.js';
27
-
28
- console.info('[Quasar] Running SPA.');
29
-
30
- const publicPath = `/`;
31
-
32
- async function start({ app, router }) {
33
- app.use(router);
34
-
35
- app.mount('#q-app');
36
- }
37
-
38
- createQuasarApp(createApp, quasarUserOptions).then(start);