@beclab/olaresid 0.1.2 → 0.1.4

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.
@@ -3,13 +3,17 @@ import { TransactionResult } from './index';
3
3
  import { parseContractError } from '../utils/error-parser';
4
4
  import { TagTypeBuilder } from '../utils/tag-type-builder';
5
5
  import { TagAbiCodec } from '../utils/tag-abi-codec';
6
+ import { normalizeToDomain } from '../utils/olares-id';
6
7
 
7
8
  /**
8
9
  * Tag Operation Context
9
10
  * Provides complete Tag management functionality
10
11
  */
11
12
  export class TagContext {
12
- constructor(private console: DIDConsole, private fromDomain: string) {}
13
+ constructor(private console: DIDConsole, private fromDomain: string) {
14
+ // Support Olares ID format (user@domain.com)
15
+ this.fromDomain = normalizeToDomain(fromDomain);
16
+ }
13
17
 
14
18
  // ========================================
15
19
  // 1. Tag Type Definition Management
@@ -214,6 +218,9 @@ export class TagContext {
214
218
  tagName: string,
215
219
  value: any
216
220
  ): Promise<TransactionResult> {
221
+ // Support Olares ID format
222
+ toDomain = normalizeToDomain(toDomain);
223
+
217
224
  const contract = this.console.getSignerContractDID();
218
225
 
219
226
  // Get tag type
@@ -285,6 +292,9 @@ export class TagContext {
285
292
  * @returns Tag value, or null if not found
286
293
  */
287
294
  async getTag(toDomain: string, tagName: string): Promise<any | null> {
295
+ // Support Olares ID format
296
+ toDomain = normalizeToDomain(toDomain);
297
+
288
298
  try {
289
299
  const contract = this.console.getContractDID();
290
300
 
@@ -332,6 +342,9 @@ export class TagContext {
332
342
  toDomain: string,
333
343
  tagName: string
334
344
  ): Promise<TransactionResult> {
345
+ // Support Olares ID format
346
+ toDomain = normalizeToDomain(toDomain);
347
+
335
348
  try {
336
349
  const contract = this.console.getSignerContractDID();
337
350
  const tx = await contract.removeTag(
@@ -363,6 +376,9 @@ export class TagContext {
363
376
  * @returns Whether the tag exists
364
377
  */
365
378
  async hasTag(toDomain: string, tagName: string): Promise<boolean> {
379
+ // Support Olares ID format
380
+ toDomain = normalizeToDomain(toDomain);
381
+
366
382
  const contract = this.console.getContractDID();
367
383
  return await contract.hasTag(this.fromDomain, toDomain, tagName);
368
384
  }
@@ -373,6 +389,9 @@ export class TagContext {
373
389
  * @returns Array of Tag names
374
390
  */
375
391
  async getTagNames(toDomain: string): Promise<string[]> {
392
+ // Support Olares ID format
393
+ toDomain = normalizeToDomain(toDomain);
394
+
376
395
  const contract = this.console.getContractDID();
377
396
  const count = await contract.getTagCount(this.fromDomain, toDomain);
378
397
  const names: string[] = [];
@@ -433,6 +452,9 @@ export class TagContext {
433
452
  value: any,
434
453
  elemPath: number[] = []
435
454
  ): Promise<TransactionResult> {
455
+ // Support Olares ID format
456
+ toDomain = normalizeToDomain(toDomain);
457
+
436
458
  const contract = this.console.getSignerContractDID();
437
459
 
438
460
  // Get tag type and encode element
@@ -490,6 +512,9 @@ export class TagContext {
490
512
  tagName: string,
491
513
  elemPath: number[] = []
492
514
  ): Promise<TransactionResult> {
515
+ // Support Olares ID format
516
+ toDomain = normalizeToDomain(toDomain);
517
+
493
518
  try {
494
519
  const contract = this.console.getSignerContractDID();
495
520
  const tx = await contract.popTagElem(
@@ -536,6 +561,9 @@ export class TagContext {
536
561
  elemPath: number[],
537
562
  value: any
538
563
  ): Promise<TransactionResult> {
564
+ // Support Olares ID format
565
+ toDomain = normalizeToDomain(toDomain);
566
+
539
567
  const contract = this.console.getSignerContractDID();
540
568
 
541
569
  const tagTypeInfo = await this.getTagType(tagName);
@@ -592,6 +620,9 @@ export class TagContext {
592
620
  tagName: string,
593
621
  elemPath: number[] = []
594
622
  ): Promise<number> {
623
+ // Support Olares ID format
624
+ toDomain = normalizeToDomain(toDomain);
625
+
595
626
  const contract = this.console.getContractDID();
596
627
  const length = await contract.getTagElemLength(
597
628
  this.fromDomain,
@@ -621,6 +652,9 @@ export class TagContext {
621
652
  tagName: string,
622
653
  elemPath: number[]
623
654
  ): Promise<any | null> {
655
+ // Support Olares ID format
656
+ toDomain = normalizeToDomain(toDomain);
657
+
624
658
  try {
625
659
  const contract = this.console.getContractDID();
626
660
 
package/src/cli.ts CHANGED
@@ -15,6 +15,7 @@ import OlaresID, {
15
15
  TagTypeBuilder
16
16
  } from './index';
17
17
  import { debug } from './debug';
18
+ import { normalizeToDomain } from './utils/olares-id';
18
19
  import * as fs from 'fs';
19
20
  import * as path from 'path';
20
21
 
@@ -155,6 +156,11 @@ DID CLI Tool v${CLI_VERSION}
155
156
  USAGE:
156
157
  did-cli <command> [subcommand] [arguments] [options]
157
158
 
159
+ NOTE:
160
+ Olares ID Format: You can use @ instead of the first dot in domain names.
161
+ Example: alice@example.com is equivalent to alice.example.com
162
+ Both formats work identically in all commands!
163
+
158
164
  COMMANDS:
159
165
  Query Commands:
160
166
  info <domain> Get domain metadata
@@ -261,6 +267,14 @@ EXAMPLES:
261
267
  export PRIVATE_KEY_OR_MNEMONIC=0xYOUR_PRIVATE_KEY
262
268
  did-cli is-owner example.olares.com
263
269
 
270
+ # Olares ID format (use @ instead of first dot - like email addresses!)
271
+ # Both formats work identically: alice.example.com = alice@example.com
272
+ did-cli info alice@example.com
273
+ did-cli owner bob@sub.example.com
274
+ did-cli rsa get user@domain.com
275
+ did-cli ip set alice@example.com 192.168.1.100
276
+ did-cli tag get alice@example.com email
277
+
264
278
  # RSA key management
265
279
  did-cli rsa generate --output ./my-key.pem --key-length 4096
266
280
  did-cli rsa get example.olares.com
@@ -2266,7 +2280,10 @@ async function tagGetTagger(
2266
2280
  }
2267
2281
 
2268
2282
  async function main(): Promise<void> {
2269
- const { command, subCommand, domain, value, options } = parseArgs();
2283
+ const parsed = parseArgs();
2284
+ const { command, subCommand, value, options } = parsed;
2285
+ // Support Olares ID format (user@domain.com) by converting to standard domain format
2286
+ const domain = parsed.domain ? normalizeToDomain(parsed.domain) : undefined;
2270
2287
 
2271
2288
  if (options.help || !command || command === 'help') {
2272
2289
  showHelp();
package/src/index.ts CHANGED
@@ -6,29 +6,9 @@ import RootResolverABI from './abi/RootResolverABI';
6
6
  import RootResolver2ABI from './abi/RootResolver2ABI';
7
7
  import { debug } from './debug';
8
8
  import { parseContractError } from './utils/error-parser';
9
+ import { normalizeToDomain } from './utils/olares-id';
9
10
 
10
- import {
11
- DomainContext,
12
- DomainMetaInfo,
13
- DomainInfo,
14
- TagInfo,
15
- TransactionResult,
16
- RSAPublicKeyData,
17
- DIDKeyData,
18
- UserType,
19
- createRsaKeyPair,
20
- pemToDer,
21
- derToPem,
22
- ipv4ToBytes4,
23
- bytes4ToIpv4,
24
- generateMnemonic,
25
- getEthereumAddressFromMnemonic,
26
- getEVMPrivateKeyFromMnemonic,
27
- getDIDFromMnemonic,
28
- generateDIDKeyData,
29
- deriveDIDFromMnemonic
30
- } from './business';
31
- import { TagContext } from './business/tag-context';
11
+ import { DomainContext, TransactionResult } from './business';
32
12
 
33
13
  // Import Tag utilities
34
14
  import { TagTypeBuilder } from './utils/tag-type-builder';
@@ -57,7 +37,8 @@ export {
57
37
  getEVMPrivateKeyFromMnemonic,
58
38
  getDIDFromMnemonic,
59
39
  generateDIDKeyData,
60
- deriveDIDFromMnemonic
40
+ deriveDIDFromMnemonic,
41
+ getEd25519JwkFromMnemonic
61
42
  } from './business';
62
43
 
63
44
  type Domain = PackageDomain.Domain;
@@ -289,13 +270,16 @@ export class DIDConsole implements DIDTag.ABITypeProviderHolder {
289
270
 
290
271
  fetchDomain = (name: string) =>
291
272
  new Promise<Domain | undefined>(async (resolve, reject) => {
273
+ // Support Olares ID format (user@domain.com)
274
+ const normalizedName = normalizeToDomain(name);
275
+
292
276
  debug.group('fetchDomain');
293
277
  const hasCache = this.allDomainCache.length > 0;
294
278
  debug.info('fetchDomain--->hasCache', hasCache);
295
279
 
296
280
  if (hasCache) {
297
281
  const domain = PackageDomain.findASubtree(
298
- name,
282
+ normalizedName,
299
283
  this.allDomainCache
300
284
  );
301
285
 
@@ -303,7 +287,7 @@ export class DIDConsole implements DIDTag.ABITypeProviderHolder {
303
287
  resolve(domain);
304
288
  } else {
305
289
  const domain = await PackageDomain.syncByName(
306
- name,
290
+ normalizedName,
307
291
  await this.getContractDID()
308
292
  );
309
293
 
@@ -314,8 +298,11 @@ export class DIDConsole implements DIDTag.ABITypeProviderHolder {
314
298
 
315
299
  updateDomain = (name: string) =>
316
300
  new Promise<Domain>(async (resolve, reject) => {
301
+ // Support Olares ID format (user@domain.com)
302
+ const normalizedName = normalizeToDomain(name);
303
+
317
304
  const domain = await PackageDomain.syncByName(
318
- name,
305
+ normalizedName,
319
306
  await this.getContractDID()
320
307
  );
321
308
 
@@ -585,4 +572,7 @@ export { debug } from './debug';
585
572
  // Export Tag utilities outside namespace
586
573
  export { TagTypeBuilder, TagAbiCodec };
587
574
 
575
+ // Export Olares ID utilities
576
+ export { normalizeToDomain, normalizeToOlaresId } from './utils/olares-id';
577
+
588
578
  export default OlaresID;
@@ -8,43 +8,13 @@
8
8
 
9
9
  import * as bip39 from 'bip39';
10
10
  import * as varint from 'varint';
11
+ import { base58btc } from 'multiformats/bases/base58';
12
+ import { base64url } from 'multiformats/bases/base64';
11
13
 
12
14
  // Browser globals type declaration
13
15
  declare const window: any;
14
16
  declare const btoa: (input: string) => string;
15
17
 
16
- // Base58 Bitcoin alphabet
17
- const BASE58_ALPHABET =
18
- '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
19
-
20
- /**
21
- * Encode bytes to base58btc format
22
- * This is a pure implementation compatible with multiformats/bases/base58
23
- */
24
- function base58Encode(bytes: Uint8Array): string {
25
- // Convert bytes to bigint
26
- let num = 0n;
27
- for (let i = 0; i < bytes.length; i++) {
28
- num = num * 256n + BigInt(bytes[i]);
29
- }
30
-
31
- // Convert to base58
32
- let encoded = '';
33
- while (num > 0n) {
34
- const remainder = Number(num % 58n);
35
- encoded = BASE58_ALPHABET[remainder] + encoded;
36
- num = num / 58n;
37
- }
38
-
39
- // Add leading '1's for leading zero bytes
40
- for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {
41
- encoded = '1' + encoded;
42
- }
43
-
44
- // Add 'z' prefix for base58btc multibase
45
- return 'z' + encoded;
46
- }
47
-
48
18
  export interface RSAPublicKeyData {
49
19
  rsaPublicKey: string;
50
20
  rsaPrivateKey: string;
@@ -239,7 +209,7 @@ async function getID(mnemonic: string): Promise<string> {
239
209
  idBytes.set(publicKey.data(), ED25519_CODEC_ID.length);
240
210
 
241
211
  // Encode to base58btc
242
- const id = base58Encode(idBytes);
212
+ const id = base58btc.encode(idBytes);
243
213
  return id;
244
214
  }
245
215
 
@@ -268,6 +238,93 @@ export async function getDIDFromMnemonic(mnemonic: string): Promise<string> {
268
238
  return `did:key:${id}`;
269
239
  }
270
240
 
241
+ /**
242
+ * Generate Ed25519 JWK (JSON Web Key) from BIP39 mnemonic phrase
243
+ * Uses Trust Wallet Core for key derivation, ensuring compatibility with TermiPass
244
+ *
245
+ * @param mnemonic BIP39 mnemonic phrase (12, 15, 18, 21, or 24 words)
246
+ * @returns Object containing publicJwk and privateJwk in RFC 7517 format
247
+ *
248
+ * @example
249
+ * ```typescript
250
+ * const { publicJwk, privateJwk } = await getEd25519JwkFromMnemonic(mnemonic);
251
+ *
252
+ * // Public JWK (safe to share)
253
+ * console.log(publicJwk);
254
+ * // {
255
+ * // "kty": "OKP",
256
+ * // "crv": "Ed25519",
257
+ * // "alg": "EdDSA",
258
+ * // "use": "sig",
259
+ * // "kid": "did:key:z6Mk...#z6Mk...",
260
+ * // "x": "base64url-encoded-public-key"
261
+ * // }
262
+ *
263
+ * // Private JWK (keep secure!)
264
+ * console.log(privateJwk);
265
+ * // {
266
+ * // "kty": "OKP",
267
+ * // "crv": "Ed25519",
268
+ * // "alg": "EdDSA",
269
+ * // "use": "sig",
270
+ * // "kid": "did:key:z6Mk...#z6Mk...",
271
+ * // "x": "base64url-encoded-public-key",
272
+ * // "d": "base64url-encoded-private-key"
273
+ * // }
274
+ * ```
275
+ */
276
+ export async function getEd25519JwkFromMnemonic(mnemonic: string): Promise<{
277
+ publicJwk: any;
278
+ privateJwk: any;
279
+ }> {
280
+ // Validate mnemonic
281
+ if (!bip39.validateMnemonic(mnemonic)) {
282
+ throw new Error('Invalid mnemonic phrase');
283
+ }
284
+
285
+ const core = await loadWalletCore();
286
+ const { HDWallet, Curve } = core;
287
+
288
+ const wallet = HDWallet.createWithMnemonic(mnemonic, '');
289
+ const privateKey = wallet.getMasterKey(Curve.ed25519);
290
+ const publicKey = privateKey.getPublicKeyEd25519();
291
+
292
+ // Get key data
293
+ const publicKeyBytes = publicKey.data();
294
+ const privateKeyBytes = privateKey.data();
295
+
296
+ const idBytes = new Uint8Array(
297
+ publicKeyBytes.length + ED25519_CODEC_ID.length
298
+ );
299
+ idBytes.set(ED25519_CODEC_ID, 0);
300
+ idBytes.set(publicKeyBytes, ED25519_CODEC_ID.length);
301
+ const id = base58btc.encode(idBytes);
302
+ const did = `did:key:${id}`;
303
+ const keyId = `${did}#${id}`;
304
+
305
+ // Base64url encode the keys
306
+ const x = base64url.baseEncode(publicKeyBytes);
307
+ const d = base64url.baseEncode(privateKeyBytes);
308
+
309
+ // Public JWK (contains only public key material)
310
+ const publicJwk = {
311
+ kty: 'OKP', // Key Type: Octet Key Pair
312
+ crv: 'Ed25519', // Curve: Ed25519
313
+ alg: 'EdDSA', // Algorithm: EdDSA
314
+ use: 'sig', // Use: signature
315
+ kid: keyId, // Key ID
316
+ x: x // Public key parameter
317
+ };
318
+
319
+ // Private JWK (contains both public and private key material)
320
+ const privateJwk = {
321
+ ...publicJwk,
322
+ d: d // Private key parameter
323
+ };
324
+
325
+ return { publicJwk, privateJwk };
326
+ }
327
+
271
328
  /**
272
329
  * Derive both owner (Ethereum address) and DID from existing mnemonic
273
330
  *
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Olares ID Utilities
3
+ *
4
+ * Olares ID is a new format that looks like email addresses: user@domain.com
5
+ * It's essentially a domain name where the first dot (.) is replaced with an at sign (@)
6
+ *
7
+ * Examples:
8
+ * - alice.example.com → alice@example.com (Olares ID)
9
+ * - bob.sub.example.com → bob@sub.example.com (Olares ID)
10
+ */
11
+
12
+ /**
13
+ * Convert Olares ID format to standard domain format
14
+ * Replaces the first @ with a dot (.)
15
+ *
16
+ * @param input The input string (can be either Olares ID or domain format)
17
+ * @returns The normalized domain format
18
+ *
19
+ * @example
20
+ * normalizeToDomain('alice@example.com') // returns 'alice.example.com'
21
+ * normalizeToDomain('alice.example.com') // returns 'alice.example.com' (no change)
22
+ * normalizeToDomain('bob@sub.example.com') // returns 'bob.sub.example.com'
23
+ */
24
+ export function normalizeToDomain(input: string): string {
25
+ if (!input) {
26
+ return input;
27
+ }
28
+ // Replace the first @ with a dot
29
+ return input.replace('@', '.');
30
+ }
31
+
32
+ /**
33
+ * Convert standard domain format to Olares ID format
34
+ * Replaces the first dot (.) with an at sign (@)
35
+ *
36
+ * @param domain The domain name
37
+ * @returns The Olares ID format
38
+ *
39
+ * @example
40
+ * normalizeToOlaresId('alice.example.com') // returns 'alice@example.com'
41
+ * normalizeToOlaresId('bob.sub.example.com') // returns 'bob@sub.example.com'
42
+ */
43
+ export function normalizeToOlaresId(domain: string): string {
44
+ if (!domain) {
45
+ return domain;
46
+ }
47
+ // Replace the first dot with @
48
+ return domain.replace('.', '@');
49
+ }