@calimero-network/mero-js 19.4.0 → 19.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/account/account.d.ts +76 -0
- package/dist/account/account.js +0 -0
- package/dist/account/index.d.ts +2 -0
- package/dist/account/index.js +2 -0
- package/dist/account/wordlist.d.ts +16 -0
- package/dist/account/wordlist.js +273 -0
- package/dist/admin-api/admin-client.d.ts +5 -1
- package/dist/admin-api/admin-client.js +12 -0
- package/dist/admin-api/admin-types.d.ts +5 -1
- package/dist/cloud/cloud-client.d.ts +93 -0
- package/dist/cloud/cloud-client.js +84 -0
- package/dist/cloud/index.d.ts +1 -1
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +2438 -176
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.mjs +2438 -176
- package/dist/index.mjs.map +3 -3
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1057,6 +1057,33 @@ var AdminApiClient = class {
|
|
|
1057
1057
|
async listApplicationAliases() {
|
|
1058
1058
|
return unwrap(await this.httpClient.get("/admin-api/alias/list/application"));
|
|
1059
1059
|
}
|
|
1060
|
+
async createDeviceAlias(request) {
|
|
1061
|
+
return unwrap(
|
|
1062
|
+
await this.httpClient.post(
|
|
1063
|
+
"/admin-api/alias/create/device",
|
|
1064
|
+
{ alias: request.alias, deviceId: request.deviceId }
|
|
1065
|
+
)
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
async lookupDeviceAlias(name) {
|
|
1069
|
+
return unwrap(
|
|
1070
|
+
await this.httpClient.post(
|
|
1071
|
+
`/admin-api/alias/lookup/device/${encodeURIComponent(name)}`,
|
|
1072
|
+
{}
|
|
1073
|
+
)
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
async deleteDeviceAlias(name) {
|
|
1077
|
+
return unwrap(
|
|
1078
|
+
await this.httpClient.post(
|
|
1079
|
+
`/admin-api/alias/delete/device/${encodeURIComponent(name)}`,
|
|
1080
|
+
{}
|
|
1081
|
+
)
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
async listDeviceAliases() {
|
|
1085
|
+
return unwrap(await this.httpClient.get("/admin-api/alias/list/device"));
|
|
1086
|
+
}
|
|
1060
1087
|
// ---- Namespace Management ----
|
|
1061
1088
|
async listNamespaces() {
|
|
1062
1089
|
return unwrap(await this.httpClient.get("/admin-api/namespaces"));
|
|
@@ -2288,6 +2315,2326 @@ var EphemeralClient = class {
|
|
|
2288
2315
|
}
|
|
2289
2316
|
};
|
|
2290
2317
|
|
|
2318
|
+
// src/crypto/internal.ts
|
|
2319
|
+
var PKCS8_ED25519_PREFIX = new Uint8Array([
|
|
2320
|
+
48,
|
|
2321
|
+
46,
|
|
2322
|
+
2,
|
|
2323
|
+
1,
|
|
2324
|
+
0,
|
|
2325
|
+
48,
|
|
2326
|
+
5,
|
|
2327
|
+
6,
|
|
2328
|
+
3,
|
|
2329
|
+
43,
|
|
2330
|
+
101,
|
|
2331
|
+
112,
|
|
2332
|
+
4,
|
|
2333
|
+
34,
|
|
2334
|
+
4,
|
|
2335
|
+
32
|
|
2336
|
+
]);
|
|
2337
|
+
function u32le(value) {
|
|
2338
|
+
const out = new Uint8Array(4);
|
|
2339
|
+
new DataView(out.buffer).setUint32(0, value, true);
|
|
2340
|
+
return out;
|
|
2341
|
+
}
|
|
2342
|
+
function hex(bytes) {
|
|
2343
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
2344
|
+
}
|
|
2345
|
+
function fromHex(value, label, expectedBytes) {
|
|
2346
|
+
const clean = value.trim();
|
|
2347
|
+
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {
|
|
2348
|
+
throw new Error(
|
|
2349
|
+
`${label} must be ${expectedBytes * 2} hex characters, got ${clean.length}`
|
|
2350
|
+
);
|
|
2351
|
+
}
|
|
2352
|
+
const bytes = new Uint8Array(expectedBytes);
|
|
2353
|
+
for (let i = 0; i < expectedBytes; i += 1) {
|
|
2354
|
+
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
2355
|
+
}
|
|
2356
|
+
return bytes;
|
|
2357
|
+
}
|
|
2358
|
+
function u64le(value) {
|
|
2359
|
+
const out = new Uint8Array(8);
|
|
2360
|
+
new DataView(out.buffer).setBigUint64(0, BigInt(value), true);
|
|
2361
|
+
return out;
|
|
2362
|
+
}
|
|
2363
|
+
function concat(...parts) {
|
|
2364
|
+
const out = new Uint8Array(parts.reduce((total, p) => total + p.length, 0));
|
|
2365
|
+
let offset = 0;
|
|
2366
|
+
for (const part of parts) {
|
|
2367
|
+
out.set(part, offset);
|
|
2368
|
+
offset += part.length;
|
|
2369
|
+
}
|
|
2370
|
+
return out;
|
|
2371
|
+
}
|
|
2372
|
+
async function domainHash(domain, parts) {
|
|
2373
|
+
const chunks = [u64le(domain.length), domain];
|
|
2374
|
+
for (const part of parts) {
|
|
2375
|
+
chunks.push(u64le(part.length), part);
|
|
2376
|
+
}
|
|
2377
|
+
return new Uint8Array(
|
|
2378
|
+
await crypto.subtle.digest("SHA-256", concat(...chunks))
|
|
2379
|
+
);
|
|
2380
|
+
}
|
|
2381
|
+
async function importSigningKey(secretHex) {
|
|
2382
|
+
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2383
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2384
|
+
try {
|
|
2385
|
+
return await crypto.subtle.importKey(
|
|
2386
|
+
"pkcs8",
|
|
2387
|
+
pkcs8,
|
|
2388
|
+
{ name: "Ed25519" },
|
|
2389
|
+
false,
|
|
2390
|
+
["sign"]
|
|
2391
|
+
);
|
|
2392
|
+
} catch (cause) {
|
|
2393
|
+
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
2394
|
+
throw new Error(
|
|
2395
|
+
"this runtime has no WebCrypto Ed25519, so a warrant cannot be signed here. Node 18.4+, Safari 17+, Firefox 129+ and Chrome 137+ have it; otherwise mint the warrant with `merod account warrant`" + detail
|
|
2396
|
+
);
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
async function derivePublicKey(secretHex) {
|
|
2400
|
+
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2401
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2402
|
+
const key = await crypto.subtle.importKey(
|
|
2403
|
+
"pkcs8",
|
|
2404
|
+
pkcs8,
|
|
2405
|
+
{ name: "Ed25519" },
|
|
2406
|
+
true,
|
|
2407
|
+
["sign"]
|
|
2408
|
+
);
|
|
2409
|
+
const jwk = await crypto.subtle.exportKey("jwk", key);
|
|
2410
|
+
const raw = jwk.x;
|
|
2411
|
+
return Uint8Array.from(
|
|
2412
|
+
atob(raw.replace(/-/g, "+").replace(/_/g, "/")),
|
|
2413
|
+
(c) => c.charCodeAt(0)
|
|
2414
|
+
);
|
|
2415
|
+
}
|
|
2416
|
+
|
|
2417
|
+
// src/device-cert/device-cert.ts
|
|
2418
|
+
var CERT_DOMAIN = new TextEncoder().encode("calimero.device.cert.v1");
|
|
2419
|
+
var ACCOUNT_ID_DOMAIN = new TextEncoder().encode("calimero.account.genesis.v1");
|
|
2420
|
+
var DEVICE_ID_DOMAIN = new TextEncoder().encode("calimero.device.id.v1");
|
|
2421
|
+
var ACCOUNT_GENESIS_VERSION = 2;
|
|
2422
|
+
async function mintDeviceId(account, nonce) {
|
|
2423
|
+
if (nonce.length !== 16) {
|
|
2424
|
+
throw new Error(`nonce must be 16 bytes, got ${nonce.length}`);
|
|
2425
|
+
}
|
|
2426
|
+
const accountBytes = fromHex(account, "account", 32);
|
|
2427
|
+
return hex(await domainHash(DEVICE_ID_DOMAIN, [accountBytes, nonce]));
|
|
2428
|
+
}
|
|
2429
|
+
async function deviceCertPayload(input) {
|
|
2430
|
+
return domainHash(CERT_DOMAIN, [
|
|
2431
|
+
fromHex(input.account, "account", 32),
|
|
2432
|
+
fromHex(input.device, "device", 32),
|
|
2433
|
+
fromHex(input.signPublicKey, "signPublicKey", 32),
|
|
2434
|
+
fromHex(input.kemPublicKey, "kemPublicKey", 32),
|
|
2435
|
+
u32le(input.keyEpoch),
|
|
2436
|
+
u32le(input.deviceEpoch)
|
|
2437
|
+
]);
|
|
2438
|
+
}
|
|
2439
|
+
function accountProofBytes(input) {
|
|
2440
|
+
return concat(
|
|
2441
|
+
new Uint8Array([ACCOUNT_GENESIS_VERSION]),
|
|
2442
|
+
input.rootPublicKey,
|
|
2443
|
+
u32le(0),
|
|
2444
|
+
fromHex(input.account, "account", 32),
|
|
2445
|
+
fromHex(input.device, "device", 32),
|
|
2446
|
+
fromHex(input.signPublicKey, "signPublicKey", 32),
|
|
2447
|
+
fromHex(input.kemPublicKey, "kemPublicKey", 32),
|
|
2448
|
+
u32le(input.keyEpoch),
|
|
2449
|
+
u32le(input.deviceEpoch),
|
|
2450
|
+
input.signature
|
|
2451
|
+
);
|
|
2452
|
+
}
|
|
2453
|
+
async function signDeviceCert(input) {
|
|
2454
|
+
const rootPublicKey = await derivePublicKey(input.rootSecret);
|
|
2455
|
+
const account = hex(
|
|
2456
|
+
await domainHash(ACCOUNT_ID_DOMAIN, [
|
|
2457
|
+
concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey)
|
|
2458
|
+
])
|
|
2459
|
+
);
|
|
2460
|
+
const keyEpoch = 0;
|
|
2461
|
+
const payload = await deviceCertPayload({
|
|
2462
|
+
account,
|
|
2463
|
+
device: input.device,
|
|
2464
|
+
signPublicKey: input.signPublicKey,
|
|
2465
|
+
kemPublicKey: input.kemPublicKey,
|
|
2466
|
+
keyEpoch,
|
|
2467
|
+
deviceEpoch: input.deviceEpoch
|
|
2468
|
+
});
|
|
2469
|
+
const key = await importSigningKey(input.rootSecret);
|
|
2470
|
+
const signature = new Uint8Array(
|
|
2471
|
+
await crypto.subtle.sign("Ed25519", key, payload)
|
|
2472
|
+
);
|
|
2473
|
+
const credential = accountProofBytes({
|
|
2474
|
+
rootPublicKey,
|
|
2475
|
+
account,
|
|
2476
|
+
device: input.device,
|
|
2477
|
+
signPublicKey: input.signPublicKey,
|
|
2478
|
+
kemPublicKey: input.kemPublicKey,
|
|
2479
|
+
keyEpoch,
|
|
2480
|
+
deviceEpoch: input.deviceEpoch,
|
|
2481
|
+
signature
|
|
2482
|
+
});
|
|
2483
|
+
return hex(credential);
|
|
2484
|
+
}
|
|
2485
|
+
async function accountForRoot(rootSecret) {
|
|
2486
|
+
const rootPublicKey = await derivePublicKey(rootSecret);
|
|
2487
|
+
return hex(
|
|
2488
|
+
await domainHash(ACCOUNT_ID_DOMAIN, [
|
|
2489
|
+
concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey)
|
|
2490
|
+
])
|
|
2491
|
+
);
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
// src/account/wordlist.ts
|
|
2495
|
+
var ENGLISH_WORDLIST = [
|
|
2496
|
+
"abandon",
|
|
2497
|
+
"ability",
|
|
2498
|
+
"able",
|
|
2499
|
+
"about",
|
|
2500
|
+
"above",
|
|
2501
|
+
"absent",
|
|
2502
|
+
"absorb",
|
|
2503
|
+
"abstract",
|
|
2504
|
+
"absurd",
|
|
2505
|
+
"abuse",
|
|
2506
|
+
"access",
|
|
2507
|
+
"accident",
|
|
2508
|
+
"account",
|
|
2509
|
+
"accuse",
|
|
2510
|
+
"achieve",
|
|
2511
|
+
"acid",
|
|
2512
|
+
"acoustic",
|
|
2513
|
+
"acquire",
|
|
2514
|
+
"across",
|
|
2515
|
+
"act",
|
|
2516
|
+
"action",
|
|
2517
|
+
"actor",
|
|
2518
|
+
"actress",
|
|
2519
|
+
"actual",
|
|
2520
|
+
"adapt",
|
|
2521
|
+
"add",
|
|
2522
|
+
"addict",
|
|
2523
|
+
"address",
|
|
2524
|
+
"adjust",
|
|
2525
|
+
"admit",
|
|
2526
|
+
"adult",
|
|
2527
|
+
"advance",
|
|
2528
|
+
"advice",
|
|
2529
|
+
"aerobic",
|
|
2530
|
+
"affair",
|
|
2531
|
+
"afford",
|
|
2532
|
+
"afraid",
|
|
2533
|
+
"again",
|
|
2534
|
+
"age",
|
|
2535
|
+
"agent",
|
|
2536
|
+
"agree",
|
|
2537
|
+
"ahead",
|
|
2538
|
+
"aim",
|
|
2539
|
+
"air",
|
|
2540
|
+
"airport",
|
|
2541
|
+
"aisle",
|
|
2542
|
+
"alarm",
|
|
2543
|
+
"album",
|
|
2544
|
+
"alcohol",
|
|
2545
|
+
"alert",
|
|
2546
|
+
"alien",
|
|
2547
|
+
"all",
|
|
2548
|
+
"alley",
|
|
2549
|
+
"allow",
|
|
2550
|
+
"almost",
|
|
2551
|
+
"alone",
|
|
2552
|
+
"alpha",
|
|
2553
|
+
"already",
|
|
2554
|
+
"also",
|
|
2555
|
+
"alter",
|
|
2556
|
+
"always",
|
|
2557
|
+
"amateur",
|
|
2558
|
+
"amazing",
|
|
2559
|
+
"among",
|
|
2560
|
+
"amount",
|
|
2561
|
+
"amused",
|
|
2562
|
+
"analyst",
|
|
2563
|
+
"anchor",
|
|
2564
|
+
"ancient",
|
|
2565
|
+
"anger",
|
|
2566
|
+
"angle",
|
|
2567
|
+
"angry",
|
|
2568
|
+
"animal",
|
|
2569
|
+
"ankle",
|
|
2570
|
+
"announce",
|
|
2571
|
+
"annual",
|
|
2572
|
+
"another",
|
|
2573
|
+
"answer",
|
|
2574
|
+
"antenna",
|
|
2575
|
+
"antique",
|
|
2576
|
+
"anxiety",
|
|
2577
|
+
"any",
|
|
2578
|
+
"apart",
|
|
2579
|
+
"apology",
|
|
2580
|
+
"appear",
|
|
2581
|
+
"apple",
|
|
2582
|
+
"approve",
|
|
2583
|
+
"april",
|
|
2584
|
+
"arch",
|
|
2585
|
+
"arctic",
|
|
2586
|
+
"area",
|
|
2587
|
+
"arena",
|
|
2588
|
+
"argue",
|
|
2589
|
+
"arm",
|
|
2590
|
+
"armed",
|
|
2591
|
+
"armor",
|
|
2592
|
+
"army",
|
|
2593
|
+
"around",
|
|
2594
|
+
"arrange",
|
|
2595
|
+
"arrest",
|
|
2596
|
+
"arrive",
|
|
2597
|
+
"arrow",
|
|
2598
|
+
"art",
|
|
2599
|
+
"artefact",
|
|
2600
|
+
"artist",
|
|
2601
|
+
"artwork",
|
|
2602
|
+
"ask",
|
|
2603
|
+
"aspect",
|
|
2604
|
+
"assault",
|
|
2605
|
+
"asset",
|
|
2606
|
+
"assist",
|
|
2607
|
+
"assume",
|
|
2608
|
+
"asthma",
|
|
2609
|
+
"athlete",
|
|
2610
|
+
"atom",
|
|
2611
|
+
"attack",
|
|
2612
|
+
"attend",
|
|
2613
|
+
"attitude",
|
|
2614
|
+
"attract",
|
|
2615
|
+
"auction",
|
|
2616
|
+
"audit",
|
|
2617
|
+
"august",
|
|
2618
|
+
"aunt",
|
|
2619
|
+
"author",
|
|
2620
|
+
"auto",
|
|
2621
|
+
"autumn",
|
|
2622
|
+
"average",
|
|
2623
|
+
"avocado",
|
|
2624
|
+
"avoid",
|
|
2625
|
+
"awake",
|
|
2626
|
+
"aware",
|
|
2627
|
+
"away",
|
|
2628
|
+
"awesome",
|
|
2629
|
+
"awful",
|
|
2630
|
+
"awkward",
|
|
2631
|
+
"axis",
|
|
2632
|
+
"baby",
|
|
2633
|
+
"bachelor",
|
|
2634
|
+
"bacon",
|
|
2635
|
+
"badge",
|
|
2636
|
+
"bag",
|
|
2637
|
+
"balance",
|
|
2638
|
+
"balcony",
|
|
2639
|
+
"ball",
|
|
2640
|
+
"bamboo",
|
|
2641
|
+
"banana",
|
|
2642
|
+
"banner",
|
|
2643
|
+
"bar",
|
|
2644
|
+
"barely",
|
|
2645
|
+
"bargain",
|
|
2646
|
+
"barrel",
|
|
2647
|
+
"base",
|
|
2648
|
+
"basic",
|
|
2649
|
+
"basket",
|
|
2650
|
+
"battle",
|
|
2651
|
+
"beach",
|
|
2652
|
+
"bean",
|
|
2653
|
+
"beauty",
|
|
2654
|
+
"because",
|
|
2655
|
+
"become",
|
|
2656
|
+
"beef",
|
|
2657
|
+
"before",
|
|
2658
|
+
"begin",
|
|
2659
|
+
"behave",
|
|
2660
|
+
"behind",
|
|
2661
|
+
"believe",
|
|
2662
|
+
"below",
|
|
2663
|
+
"belt",
|
|
2664
|
+
"bench",
|
|
2665
|
+
"benefit",
|
|
2666
|
+
"best",
|
|
2667
|
+
"betray",
|
|
2668
|
+
"better",
|
|
2669
|
+
"between",
|
|
2670
|
+
"beyond",
|
|
2671
|
+
"bicycle",
|
|
2672
|
+
"bid",
|
|
2673
|
+
"bike",
|
|
2674
|
+
"bind",
|
|
2675
|
+
"biology",
|
|
2676
|
+
"bird",
|
|
2677
|
+
"birth",
|
|
2678
|
+
"bitter",
|
|
2679
|
+
"black",
|
|
2680
|
+
"blade",
|
|
2681
|
+
"blame",
|
|
2682
|
+
"blanket",
|
|
2683
|
+
"blast",
|
|
2684
|
+
"bleak",
|
|
2685
|
+
"bless",
|
|
2686
|
+
"blind",
|
|
2687
|
+
"blood",
|
|
2688
|
+
"blossom",
|
|
2689
|
+
"blouse",
|
|
2690
|
+
"blue",
|
|
2691
|
+
"blur",
|
|
2692
|
+
"blush",
|
|
2693
|
+
"board",
|
|
2694
|
+
"boat",
|
|
2695
|
+
"body",
|
|
2696
|
+
"boil",
|
|
2697
|
+
"bomb",
|
|
2698
|
+
"bone",
|
|
2699
|
+
"bonus",
|
|
2700
|
+
"book",
|
|
2701
|
+
"boost",
|
|
2702
|
+
"border",
|
|
2703
|
+
"boring",
|
|
2704
|
+
"borrow",
|
|
2705
|
+
"boss",
|
|
2706
|
+
"bottom",
|
|
2707
|
+
"bounce",
|
|
2708
|
+
"box",
|
|
2709
|
+
"boy",
|
|
2710
|
+
"bracket",
|
|
2711
|
+
"brain",
|
|
2712
|
+
"brand",
|
|
2713
|
+
"brass",
|
|
2714
|
+
"brave",
|
|
2715
|
+
"bread",
|
|
2716
|
+
"breeze",
|
|
2717
|
+
"brick",
|
|
2718
|
+
"bridge",
|
|
2719
|
+
"brief",
|
|
2720
|
+
"bright",
|
|
2721
|
+
"bring",
|
|
2722
|
+
"brisk",
|
|
2723
|
+
"broccoli",
|
|
2724
|
+
"broken",
|
|
2725
|
+
"bronze",
|
|
2726
|
+
"broom",
|
|
2727
|
+
"brother",
|
|
2728
|
+
"brown",
|
|
2729
|
+
"brush",
|
|
2730
|
+
"bubble",
|
|
2731
|
+
"buddy",
|
|
2732
|
+
"budget",
|
|
2733
|
+
"buffalo",
|
|
2734
|
+
"build",
|
|
2735
|
+
"bulb",
|
|
2736
|
+
"bulk",
|
|
2737
|
+
"bullet",
|
|
2738
|
+
"bundle",
|
|
2739
|
+
"bunker",
|
|
2740
|
+
"burden",
|
|
2741
|
+
"burger",
|
|
2742
|
+
"burst",
|
|
2743
|
+
"bus",
|
|
2744
|
+
"business",
|
|
2745
|
+
"busy",
|
|
2746
|
+
"butter",
|
|
2747
|
+
"buyer",
|
|
2748
|
+
"buzz",
|
|
2749
|
+
"cabbage",
|
|
2750
|
+
"cabin",
|
|
2751
|
+
"cable",
|
|
2752
|
+
"cactus",
|
|
2753
|
+
"cage",
|
|
2754
|
+
"cake",
|
|
2755
|
+
"call",
|
|
2756
|
+
"calm",
|
|
2757
|
+
"camera",
|
|
2758
|
+
"camp",
|
|
2759
|
+
"can",
|
|
2760
|
+
"canal",
|
|
2761
|
+
"cancel",
|
|
2762
|
+
"candy",
|
|
2763
|
+
"cannon",
|
|
2764
|
+
"canoe",
|
|
2765
|
+
"canvas",
|
|
2766
|
+
"canyon",
|
|
2767
|
+
"capable",
|
|
2768
|
+
"capital",
|
|
2769
|
+
"captain",
|
|
2770
|
+
"car",
|
|
2771
|
+
"carbon",
|
|
2772
|
+
"card",
|
|
2773
|
+
"cargo",
|
|
2774
|
+
"carpet",
|
|
2775
|
+
"carry",
|
|
2776
|
+
"cart",
|
|
2777
|
+
"case",
|
|
2778
|
+
"cash",
|
|
2779
|
+
"casino",
|
|
2780
|
+
"castle",
|
|
2781
|
+
"casual",
|
|
2782
|
+
"cat",
|
|
2783
|
+
"catalog",
|
|
2784
|
+
"catch",
|
|
2785
|
+
"category",
|
|
2786
|
+
"cattle",
|
|
2787
|
+
"caught",
|
|
2788
|
+
"cause",
|
|
2789
|
+
"caution",
|
|
2790
|
+
"cave",
|
|
2791
|
+
"ceiling",
|
|
2792
|
+
"celery",
|
|
2793
|
+
"cement",
|
|
2794
|
+
"census",
|
|
2795
|
+
"century",
|
|
2796
|
+
"cereal",
|
|
2797
|
+
"certain",
|
|
2798
|
+
"chair",
|
|
2799
|
+
"chalk",
|
|
2800
|
+
"champion",
|
|
2801
|
+
"change",
|
|
2802
|
+
"chaos",
|
|
2803
|
+
"chapter",
|
|
2804
|
+
"charge",
|
|
2805
|
+
"chase",
|
|
2806
|
+
"chat",
|
|
2807
|
+
"cheap",
|
|
2808
|
+
"check",
|
|
2809
|
+
"cheese",
|
|
2810
|
+
"chef",
|
|
2811
|
+
"cherry",
|
|
2812
|
+
"chest",
|
|
2813
|
+
"chicken",
|
|
2814
|
+
"chief",
|
|
2815
|
+
"child",
|
|
2816
|
+
"chimney",
|
|
2817
|
+
"choice",
|
|
2818
|
+
"choose",
|
|
2819
|
+
"chronic",
|
|
2820
|
+
"chuckle",
|
|
2821
|
+
"chunk",
|
|
2822
|
+
"churn",
|
|
2823
|
+
"cigar",
|
|
2824
|
+
"cinnamon",
|
|
2825
|
+
"circle",
|
|
2826
|
+
"citizen",
|
|
2827
|
+
"city",
|
|
2828
|
+
"civil",
|
|
2829
|
+
"claim",
|
|
2830
|
+
"clap",
|
|
2831
|
+
"clarify",
|
|
2832
|
+
"claw",
|
|
2833
|
+
"clay",
|
|
2834
|
+
"clean",
|
|
2835
|
+
"clerk",
|
|
2836
|
+
"clever",
|
|
2837
|
+
"click",
|
|
2838
|
+
"client",
|
|
2839
|
+
"cliff",
|
|
2840
|
+
"climb",
|
|
2841
|
+
"clinic",
|
|
2842
|
+
"clip",
|
|
2843
|
+
"clock",
|
|
2844
|
+
"clog",
|
|
2845
|
+
"close",
|
|
2846
|
+
"cloth",
|
|
2847
|
+
"cloud",
|
|
2848
|
+
"clown",
|
|
2849
|
+
"club",
|
|
2850
|
+
"clump",
|
|
2851
|
+
"cluster",
|
|
2852
|
+
"clutch",
|
|
2853
|
+
"coach",
|
|
2854
|
+
"coast",
|
|
2855
|
+
"coconut",
|
|
2856
|
+
"code",
|
|
2857
|
+
"coffee",
|
|
2858
|
+
"coil",
|
|
2859
|
+
"coin",
|
|
2860
|
+
"collect",
|
|
2861
|
+
"color",
|
|
2862
|
+
"column",
|
|
2863
|
+
"combine",
|
|
2864
|
+
"come",
|
|
2865
|
+
"comfort",
|
|
2866
|
+
"comic",
|
|
2867
|
+
"common",
|
|
2868
|
+
"company",
|
|
2869
|
+
"concert",
|
|
2870
|
+
"conduct",
|
|
2871
|
+
"confirm",
|
|
2872
|
+
"congress",
|
|
2873
|
+
"connect",
|
|
2874
|
+
"consider",
|
|
2875
|
+
"control",
|
|
2876
|
+
"convince",
|
|
2877
|
+
"cook",
|
|
2878
|
+
"cool",
|
|
2879
|
+
"copper",
|
|
2880
|
+
"copy",
|
|
2881
|
+
"coral",
|
|
2882
|
+
"core",
|
|
2883
|
+
"corn",
|
|
2884
|
+
"correct",
|
|
2885
|
+
"cost",
|
|
2886
|
+
"cotton",
|
|
2887
|
+
"couch",
|
|
2888
|
+
"country",
|
|
2889
|
+
"couple",
|
|
2890
|
+
"course",
|
|
2891
|
+
"cousin",
|
|
2892
|
+
"cover",
|
|
2893
|
+
"coyote",
|
|
2894
|
+
"crack",
|
|
2895
|
+
"cradle",
|
|
2896
|
+
"craft",
|
|
2897
|
+
"cram",
|
|
2898
|
+
"crane",
|
|
2899
|
+
"crash",
|
|
2900
|
+
"crater",
|
|
2901
|
+
"crawl",
|
|
2902
|
+
"crazy",
|
|
2903
|
+
"cream",
|
|
2904
|
+
"credit",
|
|
2905
|
+
"creek",
|
|
2906
|
+
"crew",
|
|
2907
|
+
"cricket",
|
|
2908
|
+
"crime",
|
|
2909
|
+
"crisp",
|
|
2910
|
+
"critic",
|
|
2911
|
+
"crop",
|
|
2912
|
+
"cross",
|
|
2913
|
+
"crouch",
|
|
2914
|
+
"crowd",
|
|
2915
|
+
"crucial",
|
|
2916
|
+
"cruel",
|
|
2917
|
+
"cruise",
|
|
2918
|
+
"crumble",
|
|
2919
|
+
"crunch",
|
|
2920
|
+
"crush",
|
|
2921
|
+
"cry",
|
|
2922
|
+
"crystal",
|
|
2923
|
+
"cube",
|
|
2924
|
+
"culture",
|
|
2925
|
+
"cup",
|
|
2926
|
+
"cupboard",
|
|
2927
|
+
"curious",
|
|
2928
|
+
"current",
|
|
2929
|
+
"curtain",
|
|
2930
|
+
"curve",
|
|
2931
|
+
"cushion",
|
|
2932
|
+
"custom",
|
|
2933
|
+
"cute",
|
|
2934
|
+
"cycle",
|
|
2935
|
+
"dad",
|
|
2936
|
+
"damage",
|
|
2937
|
+
"damp",
|
|
2938
|
+
"dance",
|
|
2939
|
+
"danger",
|
|
2940
|
+
"daring",
|
|
2941
|
+
"dash",
|
|
2942
|
+
"daughter",
|
|
2943
|
+
"dawn",
|
|
2944
|
+
"day",
|
|
2945
|
+
"deal",
|
|
2946
|
+
"debate",
|
|
2947
|
+
"debris",
|
|
2948
|
+
"decade",
|
|
2949
|
+
"december",
|
|
2950
|
+
"decide",
|
|
2951
|
+
"decline",
|
|
2952
|
+
"decorate",
|
|
2953
|
+
"decrease",
|
|
2954
|
+
"deer",
|
|
2955
|
+
"defense",
|
|
2956
|
+
"define",
|
|
2957
|
+
"defy",
|
|
2958
|
+
"degree",
|
|
2959
|
+
"delay",
|
|
2960
|
+
"deliver",
|
|
2961
|
+
"demand",
|
|
2962
|
+
"demise",
|
|
2963
|
+
"denial",
|
|
2964
|
+
"dentist",
|
|
2965
|
+
"deny",
|
|
2966
|
+
"depart",
|
|
2967
|
+
"depend",
|
|
2968
|
+
"deposit",
|
|
2969
|
+
"depth",
|
|
2970
|
+
"deputy",
|
|
2971
|
+
"derive",
|
|
2972
|
+
"describe",
|
|
2973
|
+
"desert",
|
|
2974
|
+
"design",
|
|
2975
|
+
"desk",
|
|
2976
|
+
"despair",
|
|
2977
|
+
"destroy",
|
|
2978
|
+
"detail",
|
|
2979
|
+
"detect",
|
|
2980
|
+
"develop",
|
|
2981
|
+
"device",
|
|
2982
|
+
"devote",
|
|
2983
|
+
"diagram",
|
|
2984
|
+
"dial",
|
|
2985
|
+
"diamond",
|
|
2986
|
+
"diary",
|
|
2987
|
+
"dice",
|
|
2988
|
+
"diesel",
|
|
2989
|
+
"diet",
|
|
2990
|
+
"differ",
|
|
2991
|
+
"digital",
|
|
2992
|
+
"dignity",
|
|
2993
|
+
"dilemma",
|
|
2994
|
+
"dinner",
|
|
2995
|
+
"dinosaur",
|
|
2996
|
+
"direct",
|
|
2997
|
+
"dirt",
|
|
2998
|
+
"disagree",
|
|
2999
|
+
"discover",
|
|
3000
|
+
"disease",
|
|
3001
|
+
"dish",
|
|
3002
|
+
"dismiss",
|
|
3003
|
+
"disorder",
|
|
3004
|
+
"display",
|
|
3005
|
+
"distance",
|
|
3006
|
+
"divert",
|
|
3007
|
+
"divide",
|
|
3008
|
+
"divorce",
|
|
3009
|
+
"dizzy",
|
|
3010
|
+
"doctor",
|
|
3011
|
+
"document",
|
|
3012
|
+
"dog",
|
|
3013
|
+
"doll",
|
|
3014
|
+
"dolphin",
|
|
3015
|
+
"domain",
|
|
3016
|
+
"donate",
|
|
3017
|
+
"donkey",
|
|
3018
|
+
"donor",
|
|
3019
|
+
"door",
|
|
3020
|
+
"dose",
|
|
3021
|
+
"double",
|
|
3022
|
+
"dove",
|
|
3023
|
+
"draft",
|
|
3024
|
+
"dragon",
|
|
3025
|
+
"drama",
|
|
3026
|
+
"drastic",
|
|
3027
|
+
"draw",
|
|
3028
|
+
"dream",
|
|
3029
|
+
"dress",
|
|
3030
|
+
"drift",
|
|
3031
|
+
"drill",
|
|
3032
|
+
"drink",
|
|
3033
|
+
"drip",
|
|
3034
|
+
"drive",
|
|
3035
|
+
"drop",
|
|
3036
|
+
"drum",
|
|
3037
|
+
"dry",
|
|
3038
|
+
"duck",
|
|
3039
|
+
"dumb",
|
|
3040
|
+
"dune",
|
|
3041
|
+
"during",
|
|
3042
|
+
"dust",
|
|
3043
|
+
"dutch",
|
|
3044
|
+
"duty",
|
|
3045
|
+
"dwarf",
|
|
3046
|
+
"dynamic",
|
|
3047
|
+
"eager",
|
|
3048
|
+
"eagle",
|
|
3049
|
+
"early",
|
|
3050
|
+
"earn",
|
|
3051
|
+
"earth",
|
|
3052
|
+
"easily",
|
|
3053
|
+
"east",
|
|
3054
|
+
"easy",
|
|
3055
|
+
"echo",
|
|
3056
|
+
"ecology",
|
|
3057
|
+
"economy",
|
|
3058
|
+
"edge",
|
|
3059
|
+
"edit",
|
|
3060
|
+
"educate",
|
|
3061
|
+
"effort",
|
|
3062
|
+
"egg",
|
|
3063
|
+
"eight",
|
|
3064
|
+
"either",
|
|
3065
|
+
"elbow",
|
|
3066
|
+
"elder",
|
|
3067
|
+
"electric",
|
|
3068
|
+
"elegant",
|
|
3069
|
+
"element",
|
|
3070
|
+
"elephant",
|
|
3071
|
+
"elevator",
|
|
3072
|
+
"elite",
|
|
3073
|
+
"else",
|
|
3074
|
+
"embark",
|
|
3075
|
+
"embody",
|
|
3076
|
+
"embrace",
|
|
3077
|
+
"emerge",
|
|
3078
|
+
"emotion",
|
|
3079
|
+
"employ",
|
|
3080
|
+
"empower",
|
|
3081
|
+
"empty",
|
|
3082
|
+
"enable",
|
|
3083
|
+
"enact",
|
|
3084
|
+
"end",
|
|
3085
|
+
"endless",
|
|
3086
|
+
"endorse",
|
|
3087
|
+
"enemy",
|
|
3088
|
+
"energy",
|
|
3089
|
+
"enforce",
|
|
3090
|
+
"engage",
|
|
3091
|
+
"engine",
|
|
3092
|
+
"enhance",
|
|
3093
|
+
"enjoy",
|
|
3094
|
+
"enlist",
|
|
3095
|
+
"enough",
|
|
3096
|
+
"enrich",
|
|
3097
|
+
"enroll",
|
|
3098
|
+
"ensure",
|
|
3099
|
+
"enter",
|
|
3100
|
+
"entire",
|
|
3101
|
+
"entry",
|
|
3102
|
+
"envelope",
|
|
3103
|
+
"episode",
|
|
3104
|
+
"equal",
|
|
3105
|
+
"equip",
|
|
3106
|
+
"era",
|
|
3107
|
+
"erase",
|
|
3108
|
+
"erode",
|
|
3109
|
+
"erosion",
|
|
3110
|
+
"error",
|
|
3111
|
+
"erupt",
|
|
3112
|
+
"escape",
|
|
3113
|
+
"essay",
|
|
3114
|
+
"essence",
|
|
3115
|
+
"estate",
|
|
3116
|
+
"eternal",
|
|
3117
|
+
"ethics",
|
|
3118
|
+
"evidence",
|
|
3119
|
+
"evil",
|
|
3120
|
+
"evoke",
|
|
3121
|
+
"evolve",
|
|
3122
|
+
"exact",
|
|
3123
|
+
"example",
|
|
3124
|
+
"excess",
|
|
3125
|
+
"exchange",
|
|
3126
|
+
"excite",
|
|
3127
|
+
"exclude",
|
|
3128
|
+
"excuse",
|
|
3129
|
+
"execute",
|
|
3130
|
+
"exercise",
|
|
3131
|
+
"exhaust",
|
|
3132
|
+
"exhibit",
|
|
3133
|
+
"exile",
|
|
3134
|
+
"exist",
|
|
3135
|
+
"exit",
|
|
3136
|
+
"exotic",
|
|
3137
|
+
"expand",
|
|
3138
|
+
"expect",
|
|
3139
|
+
"expire",
|
|
3140
|
+
"explain",
|
|
3141
|
+
"expose",
|
|
3142
|
+
"express",
|
|
3143
|
+
"extend",
|
|
3144
|
+
"extra",
|
|
3145
|
+
"eye",
|
|
3146
|
+
"eyebrow",
|
|
3147
|
+
"fabric",
|
|
3148
|
+
"face",
|
|
3149
|
+
"faculty",
|
|
3150
|
+
"fade",
|
|
3151
|
+
"faint",
|
|
3152
|
+
"faith",
|
|
3153
|
+
"fall",
|
|
3154
|
+
"false",
|
|
3155
|
+
"fame",
|
|
3156
|
+
"family",
|
|
3157
|
+
"famous",
|
|
3158
|
+
"fan",
|
|
3159
|
+
"fancy",
|
|
3160
|
+
"fantasy",
|
|
3161
|
+
"farm",
|
|
3162
|
+
"fashion",
|
|
3163
|
+
"fat",
|
|
3164
|
+
"fatal",
|
|
3165
|
+
"father",
|
|
3166
|
+
"fatigue",
|
|
3167
|
+
"fault",
|
|
3168
|
+
"favorite",
|
|
3169
|
+
"feature",
|
|
3170
|
+
"february",
|
|
3171
|
+
"federal",
|
|
3172
|
+
"fee",
|
|
3173
|
+
"feed",
|
|
3174
|
+
"feel",
|
|
3175
|
+
"female",
|
|
3176
|
+
"fence",
|
|
3177
|
+
"festival",
|
|
3178
|
+
"fetch",
|
|
3179
|
+
"fever",
|
|
3180
|
+
"few",
|
|
3181
|
+
"fiber",
|
|
3182
|
+
"fiction",
|
|
3183
|
+
"field",
|
|
3184
|
+
"figure",
|
|
3185
|
+
"file",
|
|
3186
|
+
"film",
|
|
3187
|
+
"filter",
|
|
3188
|
+
"final",
|
|
3189
|
+
"find",
|
|
3190
|
+
"fine",
|
|
3191
|
+
"finger",
|
|
3192
|
+
"finish",
|
|
3193
|
+
"fire",
|
|
3194
|
+
"firm",
|
|
3195
|
+
"first",
|
|
3196
|
+
"fiscal",
|
|
3197
|
+
"fish",
|
|
3198
|
+
"fit",
|
|
3199
|
+
"fitness",
|
|
3200
|
+
"fix",
|
|
3201
|
+
"flag",
|
|
3202
|
+
"flame",
|
|
3203
|
+
"flash",
|
|
3204
|
+
"flat",
|
|
3205
|
+
"flavor",
|
|
3206
|
+
"flee",
|
|
3207
|
+
"flight",
|
|
3208
|
+
"flip",
|
|
3209
|
+
"float",
|
|
3210
|
+
"flock",
|
|
3211
|
+
"floor",
|
|
3212
|
+
"flower",
|
|
3213
|
+
"fluid",
|
|
3214
|
+
"flush",
|
|
3215
|
+
"fly",
|
|
3216
|
+
"foam",
|
|
3217
|
+
"focus",
|
|
3218
|
+
"fog",
|
|
3219
|
+
"foil",
|
|
3220
|
+
"fold",
|
|
3221
|
+
"follow",
|
|
3222
|
+
"food",
|
|
3223
|
+
"foot",
|
|
3224
|
+
"force",
|
|
3225
|
+
"forest",
|
|
3226
|
+
"forget",
|
|
3227
|
+
"fork",
|
|
3228
|
+
"fortune",
|
|
3229
|
+
"forum",
|
|
3230
|
+
"forward",
|
|
3231
|
+
"fossil",
|
|
3232
|
+
"foster",
|
|
3233
|
+
"found",
|
|
3234
|
+
"fox",
|
|
3235
|
+
"fragile",
|
|
3236
|
+
"frame",
|
|
3237
|
+
"frequent",
|
|
3238
|
+
"fresh",
|
|
3239
|
+
"friend",
|
|
3240
|
+
"fringe",
|
|
3241
|
+
"frog",
|
|
3242
|
+
"front",
|
|
3243
|
+
"frost",
|
|
3244
|
+
"frown",
|
|
3245
|
+
"frozen",
|
|
3246
|
+
"fruit",
|
|
3247
|
+
"fuel",
|
|
3248
|
+
"fun",
|
|
3249
|
+
"funny",
|
|
3250
|
+
"furnace",
|
|
3251
|
+
"fury",
|
|
3252
|
+
"future",
|
|
3253
|
+
"gadget",
|
|
3254
|
+
"gain",
|
|
3255
|
+
"galaxy",
|
|
3256
|
+
"gallery",
|
|
3257
|
+
"game",
|
|
3258
|
+
"gap",
|
|
3259
|
+
"garage",
|
|
3260
|
+
"garbage",
|
|
3261
|
+
"garden",
|
|
3262
|
+
"garlic",
|
|
3263
|
+
"garment",
|
|
3264
|
+
"gas",
|
|
3265
|
+
"gasp",
|
|
3266
|
+
"gate",
|
|
3267
|
+
"gather",
|
|
3268
|
+
"gauge",
|
|
3269
|
+
"gaze",
|
|
3270
|
+
"general",
|
|
3271
|
+
"genius",
|
|
3272
|
+
"genre",
|
|
3273
|
+
"gentle",
|
|
3274
|
+
"genuine",
|
|
3275
|
+
"gesture",
|
|
3276
|
+
"ghost",
|
|
3277
|
+
"giant",
|
|
3278
|
+
"gift",
|
|
3279
|
+
"giggle",
|
|
3280
|
+
"ginger",
|
|
3281
|
+
"giraffe",
|
|
3282
|
+
"girl",
|
|
3283
|
+
"give",
|
|
3284
|
+
"glad",
|
|
3285
|
+
"glance",
|
|
3286
|
+
"glare",
|
|
3287
|
+
"glass",
|
|
3288
|
+
"glide",
|
|
3289
|
+
"glimpse",
|
|
3290
|
+
"globe",
|
|
3291
|
+
"gloom",
|
|
3292
|
+
"glory",
|
|
3293
|
+
"glove",
|
|
3294
|
+
"glow",
|
|
3295
|
+
"glue",
|
|
3296
|
+
"goat",
|
|
3297
|
+
"goddess",
|
|
3298
|
+
"gold",
|
|
3299
|
+
"good",
|
|
3300
|
+
"goose",
|
|
3301
|
+
"gorilla",
|
|
3302
|
+
"gospel",
|
|
3303
|
+
"gossip",
|
|
3304
|
+
"govern",
|
|
3305
|
+
"gown",
|
|
3306
|
+
"grab",
|
|
3307
|
+
"grace",
|
|
3308
|
+
"grain",
|
|
3309
|
+
"grant",
|
|
3310
|
+
"grape",
|
|
3311
|
+
"grass",
|
|
3312
|
+
"gravity",
|
|
3313
|
+
"great",
|
|
3314
|
+
"green",
|
|
3315
|
+
"grid",
|
|
3316
|
+
"grief",
|
|
3317
|
+
"grit",
|
|
3318
|
+
"grocery",
|
|
3319
|
+
"group",
|
|
3320
|
+
"grow",
|
|
3321
|
+
"grunt",
|
|
3322
|
+
"guard",
|
|
3323
|
+
"guess",
|
|
3324
|
+
"guide",
|
|
3325
|
+
"guilt",
|
|
3326
|
+
"guitar",
|
|
3327
|
+
"gun",
|
|
3328
|
+
"gym",
|
|
3329
|
+
"habit",
|
|
3330
|
+
"hair",
|
|
3331
|
+
"half",
|
|
3332
|
+
"hammer",
|
|
3333
|
+
"hamster",
|
|
3334
|
+
"hand",
|
|
3335
|
+
"happy",
|
|
3336
|
+
"harbor",
|
|
3337
|
+
"hard",
|
|
3338
|
+
"harsh",
|
|
3339
|
+
"harvest",
|
|
3340
|
+
"hat",
|
|
3341
|
+
"have",
|
|
3342
|
+
"hawk",
|
|
3343
|
+
"hazard",
|
|
3344
|
+
"head",
|
|
3345
|
+
"health",
|
|
3346
|
+
"heart",
|
|
3347
|
+
"heavy",
|
|
3348
|
+
"hedgehog",
|
|
3349
|
+
"height",
|
|
3350
|
+
"hello",
|
|
3351
|
+
"helmet",
|
|
3352
|
+
"help",
|
|
3353
|
+
"hen",
|
|
3354
|
+
"hero",
|
|
3355
|
+
"hidden",
|
|
3356
|
+
"high",
|
|
3357
|
+
"hill",
|
|
3358
|
+
"hint",
|
|
3359
|
+
"hip",
|
|
3360
|
+
"hire",
|
|
3361
|
+
"history",
|
|
3362
|
+
"hobby",
|
|
3363
|
+
"hockey",
|
|
3364
|
+
"hold",
|
|
3365
|
+
"hole",
|
|
3366
|
+
"holiday",
|
|
3367
|
+
"hollow",
|
|
3368
|
+
"home",
|
|
3369
|
+
"honey",
|
|
3370
|
+
"hood",
|
|
3371
|
+
"hope",
|
|
3372
|
+
"horn",
|
|
3373
|
+
"horror",
|
|
3374
|
+
"horse",
|
|
3375
|
+
"hospital",
|
|
3376
|
+
"host",
|
|
3377
|
+
"hotel",
|
|
3378
|
+
"hour",
|
|
3379
|
+
"hover",
|
|
3380
|
+
"hub",
|
|
3381
|
+
"huge",
|
|
3382
|
+
"human",
|
|
3383
|
+
"humble",
|
|
3384
|
+
"humor",
|
|
3385
|
+
"hundred",
|
|
3386
|
+
"hungry",
|
|
3387
|
+
"hunt",
|
|
3388
|
+
"hurdle",
|
|
3389
|
+
"hurry",
|
|
3390
|
+
"hurt",
|
|
3391
|
+
"husband",
|
|
3392
|
+
"hybrid",
|
|
3393
|
+
"ice",
|
|
3394
|
+
"icon",
|
|
3395
|
+
"idea",
|
|
3396
|
+
"identify",
|
|
3397
|
+
"idle",
|
|
3398
|
+
"ignore",
|
|
3399
|
+
"ill",
|
|
3400
|
+
"illegal",
|
|
3401
|
+
"illness",
|
|
3402
|
+
"image",
|
|
3403
|
+
"imitate",
|
|
3404
|
+
"immense",
|
|
3405
|
+
"immune",
|
|
3406
|
+
"impact",
|
|
3407
|
+
"impose",
|
|
3408
|
+
"improve",
|
|
3409
|
+
"impulse",
|
|
3410
|
+
"inch",
|
|
3411
|
+
"include",
|
|
3412
|
+
"income",
|
|
3413
|
+
"increase",
|
|
3414
|
+
"index",
|
|
3415
|
+
"indicate",
|
|
3416
|
+
"indoor",
|
|
3417
|
+
"industry",
|
|
3418
|
+
"infant",
|
|
3419
|
+
"inflict",
|
|
3420
|
+
"inform",
|
|
3421
|
+
"inhale",
|
|
3422
|
+
"inherit",
|
|
3423
|
+
"initial",
|
|
3424
|
+
"inject",
|
|
3425
|
+
"injury",
|
|
3426
|
+
"inmate",
|
|
3427
|
+
"inner",
|
|
3428
|
+
"innocent",
|
|
3429
|
+
"input",
|
|
3430
|
+
"inquiry",
|
|
3431
|
+
"insane",
|
|
3432
|
+
"insect",
|
|
3433
|
+
"inside",
|
|
3434
|
+
"inspire",
|
|
3435
|
+
"install",
|
|
3436
|
+
"intact",
|
|
3437
|
+
"interest",
|
|
3438
|
+
"into",
|
|
3439
|
+
"invest",
|
|
3440
|
+
"invite",
|
|
3441
|
+
"involve",
|
|
3442
|
+
"iron",
|
|
3443
|
+
"island",
|
|
3444
|
+
"isolate",
|
|
3445
|
+
"issue",
|
|
3446
|
+
"item",
|
|
3447
|
+
"ivory",
|
|
3448
|
+
"jacket",
|
|
3449
|
+
"jaguar",
|
|
3450
|
+
"jar",
|
|
3451
|
+
"jazz",
|
|
3452
|
+
"jealous",
|
|
3453
|
+
"jeans",
|
|
3454
|
+
"jelly",
|
|
3455
|
+
"jewel",
|
|
3456
|
+
"job",
|
|
3457
|
+
"join",
|
|
3458
|
+
"joke",
|
|
3459
|
+
"journey",
|
|
3460
|
+
"joy",
|
|
3461
|
+
"judge",
|
|
3462
|
+
"juice",
|
|
3463
|
+
"jump",
|
|
3464
|
+
"jungle",
|
|
3465
|
+
"junior",
|
|
3466
|
+
"junk",
|
|
3467
|
+
"just",
|
|
3468
|
+
"kangaroo",
|
|
3469
|
+
"keen",
|
|
3470
|
+
"keep",
|
|
3471
|
+
"ketchup",
|
|
3472
|
+
"key",
|
|
3473
|
+
"kick",
|
|
3474
|
+
"kid",
|
|
3475
|
+
"kidney",
|
|
3476
|
+
"kind",
|
|
3477
|
+
"kingdom",
|
|
3478
|
+
"kiss",
|
|
3479
|
+
"kit",
|
|
3480
|
+
"kitchen",
|
|
3481
|
+
"kite",
|
|
3482
|
+
"kitten",
|
|
3483
|
+
"kiwi",
|
|
3484
|
+
"knee",
|
|
3485
|
+
"knife",
|
|
3486
|
+
"knock",
|
|
3487
|
+
"know",
|
|
3488
|
+
"lab",
|
|
3489
|
+
"label",
|
|
3490
|
+
"labor",
|
|
3491
|
+
"ladder",
|
|
3492
|
+
"lady",
|
|
3493
|
+
"lake",
|
|
3494
|
+
"lamp",
|
|
3495
|
+
"language",
|
|
3496
|
+
"laptop",
|
|
3497
|
+
"large",
|
|
3498
|
+
"later",
|
|
3499
|
+
"latin",
|
|
3500
|
+
"laugh",
|
|
3501
|
+
"laundry",
|
|
3502
|
+
"lava",
|
|
3503
|
+
"law",
|
|
3504
|
+
"lawn",
|
|
3505
|
+
"lawsuit",
|
|
3506
|
+
"layer",
|
|
3507
|
+
"lazy",
|
|
3508
|
+
"leader",
|
|
3509
|
+
"leaf",
|
|
3510
|
+
"learn",
|
|
3511
|
+
"leave",
|
|
3512
|
+
"lecture",
|
|
3513
|
+
"left",
|
|
3514
|
+
"leg",
|
|
3515
|
+
"legal",
|
|
3516
|
+
"legend",
|
|
3517
|
+
"leisure",
|
|
3518
|
+
"lemon",
|
|
3519
|
+
"lend",
|
|
3520
|
+
"length",
|
|
3521
|
+
"lens",
|
|
3522
|
+
"leopard",
|
|
3523
|
+
"lesson",
|
|
3524
|
+
"letter",
|
|
3525
|
+
"level",
|
|
3526
|
+
"liar",
|
|
3527
|
+
"liberty",
|
|
3528
|
+
"library",
|
|
3529
|
+
"license",
|
|
3530
|
+
"life",
|
|
3531
|
+
"lift",
|
|
3532
|
+
"light",
|
|
3533
|
+
"like",
|
|
3534
|
+
"limb",
|
|
3535
|
+
"limit",
|
|
3536
|
+
"link",
|
|
3537
|
+
"lion",
|
|
3538
|
+
"liquid",
|
|
3539
|
+
"list",
|
|
3540
|
+
"little",
|
|
3541
|
+
"live",
|
|
3542
|
+
"lizard",
|
|
3543
|
+
"load",
|
|
3544
|
+
"loan",
|
|
3545
|
+
"lobster",
|
|
3546
|
+
"local",
|
|
3547
|
+
"lock",
|
|
3548
|
+
"logic",
|
|
3549
|
+
"lonely",
|
|
3550
|
+
"long",
|
|
3551
|
+
"loop",
|
|
3552
|
+
"lottery",
|
|
3553
|
+
"loud",
|
|
3554
|
+
"lounge",
|
|
3555
|
+
"love",
|
|
3556
|
+
"loyal",
|
|
3557
|
+
"lucky",
|
|
3558
|
+
"luggage",
|
|
3559
|
+
"lumber",
|
|
3560
|
+
"lunar",
|
|
3561
|
+
"lunch",
|
|
3562
|
+
"luxury",
|
|
3563
|
+
"lyrics",
|
|
3564
|
+
"machine",
|
|
3565
|
+
"mad",
|
|
3566
|
+
"magic",
|
|
3567
|
+
"magnet",
|
|
3568
|
+
"maid",
|
|
3569
|
+
"mail",
|
|
3570
|
+
"main",
|
|
3571
|
+
"major",
|
|
3572
|
+
"make",
|
|
3573
|
+
"mammal",
|
|
3574
|
+
"man",
|
|
3575
|
+
"manage",
|
|
3576
|
+
"mandate",
|
|
3577
|
+
"mango",
|
|
3578
|
+
"mansion",
|
|
3579
|
+
"manual",
|
|
3580
|
+
"maple",
|
|
3581
|
+
"marble",
|
|
3582
|
+
"march",
|
|
3583
|
+
"margin",
|
|
3584
|
+
"marine",
|
|
3585
|
+
"market",
|
|
3586
|
+
"marriage",
|
|
3587
|
+
"mask",
|
|
3588
|
+
"mass",
|
|
3589
|
+
"master",
|
|
3590
|
+
"match",
|
|
3591
|
+
"material",
|
|
3592
|
+
"math",
|
|
3593
|
+
"matrix",
|
|
3594
|
+
"matter",
|
|
3595
|
+
"maximum",
|
|
3596
|
+
"maze",
|
|
3597
|
+
"meadow",
|
|
3598
|
+
"mean",
|
|
3599
|
+
"measure",
|
|
3600
|
+
"meat",
|
|
3601
|
+
"mechanic",
|
|
3602
|
+
"medal",
|
|
3603
|
+
"media",
|
|
3604
|
+
"melody",
|
|
3605
|
+
"melt",
|
|
3606
|
+
"member",
|
|
3607
|
+
"memory",
|
|
3608
|
+
"mention",
|
|
3609
|
+
"menu",
|
|
3610
|
+
"mercy",
|
|
3611
|
+
"merge",
|
|
3612
|
+
"merit",
|
|
3613
|
+
"merry",
|
|
3614
|
+
"mesh",
|
|
3615
|
+
"message",
|
|
3616
|
+
"metal",
|
|
3617
|
+
"method",
|
|
3618
|
+
"middle",
|
|
3619
|
+
"midnight",
|
|
3620
|
+
"milk",
|
|
3621
|
+
"million",
|
|
3622
|
+
"mimic",
|
|
3623
|
+
"mind",
|
|
3624
|
+
"minimum",
|
|
3625
|
+
"minor",
|
|
3626
|
+
"minute",
|
|
3627
|
+
"miracle",
|
|
3628
|
+
"mirror",
|
|
3629
|
+
"misery",
|
|
3630
|
+
"miss",
|
|
3631
|
+
"mistake",
|
|
3632
|
+
"mix",
|
|
3633
|
+
"mixed",
|
|
3634
|
+
"mixture",
|
|
3635
|
+
"mobile",
|
|
3636
|
+
"model",
|
|
3637
|
+
"modify",
|
|
3638
|
+
"mom",
|
|
3639
|
+
"moment",
|
|
3640
|
+
"monitor",
|
|
3641
|
+
"monkey",
|
|
3642
|
+
"monster",
|
|
3643
|
+
"month",
|
|
3644
|
+
"moon",
|
|
3645
|
+
"moral",
|
|
3646
|
+
"more",
|
|
3647
|
+
"morning",
|
|
3648
|
+
"mosquito",
|
|
3649
|
+
"mother",
|
|
3650
|
+
"motion",
|
|
3651
|
+
"motor",
|
|
3652
|
+
"mountain",
|
|
3653
|
+
"mouse",
|
|
3654
|
+
"move",
|
|
3655
|
+
"movie",
|
|
3656
|
+
"much",
|
|
3657
|
+
"muffin",
|
|
3658
|
+
"mule",
|
|
3659
|
+
"multiply",
|
|
3660
|
+
"muscle",
|
|
3661
|
+
"museum",
|
|
3662
|
+
"mushroom",
|
|
3663
|
+
"music",
|
|
3664
|
+
"must",
|
|
3665
|
+
"mutual",
|
|
3666
|
+
"myself",
|
|
3667
|
+
"mystery",
|
|
3668
|
+
"myth",
|
|
3669
|
+
"naive",
|
|
3670
|
+
"name",
|
|
3671
|
+
"napkin",
|
|
3672
|
+
"narrow",
|
|
3673
|
+
"nasty",
|
|
3674
|
+
"nation",
|
|
3675
|
+
"nature",
|
|
3676
|
+
"near",
|
|
3677
|
+
"neck",
|
|
3678
|
+
"need",
|
|
3679
|
+
"negative",
|
|
3680
|
+
"neglect",
|
|
3681
|
+
"neither",
|
|
3682
|
+
"nephew",
|
|
3683
|
+
"nerve",
|
|
3684
|
+
"nest",
|
|
3685
|
+
"net",
|
|
3686
|
+
"network",
|
|
3687
|
+
"neutral",
|
|
3688
|
+
"never",
|
|
3689
|
+
"news",
|
|
3690
|
+
"next",
|
|
3691
|
+
"nice",
|
|
3692
|
+
"night",
|
|
3693
|
+
"noble",
|
|
3694
|
+
"noise",
|
|
3695
|
+
"nominee",
|
|
3696
|
+
"noodle",
|
|
3697
|
+
"normal",
|
|
3698
|
+
"north",
|
|
3699
|
+
"nose",
|
|
3700
|
+
"notable",
|
|
3701
|
+
"note",
|
|
3702
|
+
"nothing",
|
|
3703
|
+
"notice",
|
|
3704
|
+
"novel",
|
|
3705
|
+
"now",
|
|
3706
|
+
"nuclear",
|
|
3707
|
+
"number",
|
|
3708
|
+
"nurse",
|
|
3709
|
+
"nut",
|
|
3710
|
+
"oak",
|
|
3711
|
+
"obey",
|
|
3712
|
+
"object",
|
|
3713
|
+
"oblige",
|
|
3714
|
+
"obscure",
|
|
3715
|
+
"observe",
|
|
3716
|
+
"obtain",
|
|
3717
|
+
"obvious",
|
|
3718
|
+
"occur",
|
|
3719
|
+
"ocean",
|
|
3720
|
+
"october",
|
|
3721
|
+
"odor",
|
|
3722
|
+
"off",
|
|
3723
|
+
"offer",
|
|
3724
|
+
"office",
|
|
3725
|
+
"often",
|
|
3726
|
+
"oil",
|
|
3727
|
+
"okay",
|
|
3728
|
+
"old",
|
|
3729
|
+
"olive",
|
|
3730
|
+
"olympic",
|
|
3731
|
+
"omit",
|
|
3732
|
+
"once",
|
|
3733
|
+
"one",
|
|
3734
|
+
"onion",
|
|
3735
|
+
"online",
|
|
3736
|
+
"only",
|
|
3737
|
+
"open",
|
|
3738
|
+
"opera",
|
|
3739
|
+
"opinion",
|
|
3740
|
+
"oppose",
|
|
3741
|
+
"option",
|
|
3742
|
+
"orange",
|
|
3743
|
+
"orbit",
|
|
3744
|
+
"orchard",
|
|
3745
|
+
"order",
|
|
3746
|
+
"ordinary",
|
|
3747
|
+
"organ",
|
|
3748
|
+
"orient",
|
|
3749
|
+
"original",
|
|
3750
|
+
"orphan",
|
|
3751
|
+
"ostrich",
|
|
3752
|
+
"other",
|
|
3753
|
+
"outdoor",
|
|
3754
|
+
"outer",
|
|
3755
|
+
"output",
|
|
3756
|
+
"outside",
|
|
3757
|
+
"oval",
|
|
3758
|
+
"oven",
|
|
3759
|
+
"over",
|
|
3760
|
+
"own",
|
|
3761
|
+
"owner",
|
|
3762
|
+
"oxygen",
|
|
3763
|
+
"oyster",
|
|
3764
|
+
"ozone",
|
|
3765
|
+
"pact",
|
|
3766
|
+
"paddle",
|
|
3767
|
+
"page",
|
|
3768
|
+
"pair",
|
|
3769
|
+
"palace",
|
|
3770
|
+
"palm",
|
|
3771
|
+
"panda",
|
|
3772
|
+
"panel",
|
|
3773
|
+
"panic",
|
|
3774
|
+
"panther",
|
|
3775
|
+
"paper",
|
|
3776
|
+
"parade",
|
|
3777
|
+
"parent",
|
|
3778
|
+
"park",
|
|
3779
|
+
"parrot",
|
|
3780
|
+
"party",
|
|
3781
|
+
"pass",
|
|
3782
|
+
"patch",
|
|
3783
|
+
"path",
|
|
3784
|
+
"patient",
|
|
3785
|
+
"patrol",
|
|
3786
|
+
"pattern",
|
|
3787
|
+
"pause",
|
|
3788
|
+
"pave",
|
|
3789
|
+
"payment",
|
|
3790
|
+
"peace",
|
|
3791
|
+
"peanut",
|
|
3792
|
+
"pear",
|
|
3793
|
+
"peasant",
|
|
3794
|
+
"pelican",
|
|
3795
|
+
"pen",
|
|
3796
|
+
"penalty",
|
|
3797
|
+
"pencil",
|
|
3798
|
+
"people",
|
|
3799
|
+
"pepper",
|
|
3800
|
+
"perfect",
|
|
3801
|
+
"permit",
|
|
3802
|
+
"person",
|
|
3803
|
+
"pet",
|
|
3804
|
+
"phone",
|
|
3805
|
+
"photo",
|
|
3806
|
+
"phrase",
|
|
3807
|
+
"physical",
|
|
3808
|
+
"piano",
|
|
3809
|
+
"picnic",
|
|
3810
|
+
"picture",
|
|
3811
|
+
"piece",
|
|
3812
|
+
"pig",
|
|
3813
|
+
"pigeon",
|
|
3814
|
+
"pill",
|
|
3815
|
+
"pilot",
|
|
3816
|
+
"pink",
|
|
3817
|
+
"pioneer",
|
|
3818
|
+
"pipe",
|
|
3819
|
+
"pistol",
|
|
3820
|
+
"pitch",
|
|
3821
|
+
"pizza",
|
|
3822
|
+
"place",
|
|
3823
|
+
"planet",
|
|
3824
|
+
"plastic",
|
|
3825
|
+
"plate",
|
|
3826
|
+
"play",
|
|
3827
|
+
"please",
|
|
3828
|
+
"pledge",
|
|
3829
|
+
"pluck",
|
|
3830
|
+
"plug",
|
|
3831
|
+
"plunge",
|
|
3832
|
+
"poem",
|
|
3833
|
+
"poet",
|
|
3834
|
+
"point",
|
|
3835
|
+
"polar",
|
|
3836
|
+
"pole",
|
|
3837
|
+
"police",
|
|
3838
|
+
"pond",
|
|
3839
|
+
"pony",
|
|
3840
|
+
"pool",
|
|
3841
|
+
"popular",
|
|
3842
|
+
"portion",
|
|
3843
|
+
"position",
|
|
3844
|
+
"possible",
|
|
3845
|
+
"post",
|
|
3846
|
+
"potato",
|
|
3847
|
+
"pottery",
|
|
3848
|
+
"poverty",
|
|
3849
|
+
"powder",
|
|
3850
|
+
"power",
|
|
3851
|
+
"practice",
|
|
3852
|
+
"praise",
|
|
3853
|
+
"predict",
|
|
3854
|
+
"prefer",
|
|
3855
|
+
"prepare",
|
|
3856
|
+
"present",
|
|
3857
|
+
"pretty",
|
|
3858
|
+
"prevent",
|
|
3859
|
+
"price",
|
|
3860
|
+
"pride",
|
|
3861
|
+
"primary",
|
|
3862
|
+
"print",
|
|
3863
|
+
"priority",
|
|
3864
|
+
"prison",
|
|
3865
|
+
"private",
|
|
3866
|
+
"prize",
|
|
3867
|
+
"problem",
|
|
3868
|
+
"process",
|
|
3869
|
+
"produce",
|
|
3870
|
+
"profit",
|
|
3871
|
+
"program",
|
|
3872
|
+
"project",
|
|
3873
|
+
"promote",
|
|
3874
|
+
"proof",
|
|
3875
|
+
"property",
|
|
3876
|
+
"prosper",
|
|
3877
|
+
"protect",
|
|
3878
|
+
"proud",
|
|
3879
|
+
"provide",
|
|
3880
|
+
"public",
|
|
3881
|
+
"pudding",
|
|
3882
|
+
"pull",
|
|
3883
|
+
"pulp",
|
|
3884
|
+
"pulse",
|
|
3885
|
+
"pumpkin",
|
|
3886
|
+
"punch",
|
|
3887
|
+
"pupil",
|
|
3888
|
+
"puppy",
|
|
3889
|
+
"purchase",
|
|
3890
|
+
"purity",
|
|
3891
|
+
"purpose",
|
|
3892
|
+
"purse",
|
|
3893
|
+
"push",
|
|
3894
|
+
"put",
|
|
3895
|
+
"puzzle",
|
|
3896
|
+
"pyramid",
|
|
3897
|
+
"quality",
|
|
3898
|
+
"quantum",
|
|
3899
|
+
"quarter",
|
|
3900
|
+
"question",
|
|
3901
|
+
"quick",
|
|
3902
|
+
"quit",
|
|
3903
|
+
"quiz",
|
|
3904
|
+
"quote",
|
|
3905
|
+
"rabbit",
|
|
3906
|
+
"raccoon",
|
|
3907
|
+
"race",
|
|
3908
|
+
"rack",
|
|
3909
|
+
"radar",
|
|
3910
|
+
"radio",
|
|
3911
|
+
"rail",
|
|
3912
|
+
"rain",
|
|
3913
|
+
"raise",
|
|
3914
|
+
"rally",
|
|
3915
|
+
"ramp",
|
|
3916
|
+
"ranch",
|
|
3917
|
+
"random",
|
|
3918
|
+
"range",
|
|
3919
|
+
"rapid",
|
|
3920
|
+
"rare",
|
|
3921
|
+
"rate",
|
|
3922
|
+
"rather",
|
|
3923
|
+
"raven",
|
|
3924
|
+
"raw",
|
|
3925
|
+
"razor",
|
|
3926
|
+
"ready",
|
|
3927
|
+
"real",
|
|
3928
|
+
"reason",
|
|
3929
|
+
"rebel",
|
|
3930
|
+
"rebuild",
|
|
3931
|
+
"recall",
|
|
3932
|
+
"receive",
|
|
3933
|
+
"recipe",
|
|
3934
|
+
"record",
|
|
3935
|
+
"recycle",
|
|
3936
|
+
"reduce",
|
|
3937
|
+
"reflect",
|
|
3938
|
+
"reform",
|
|
3939
|
+
"refuse",
|
|
3940
|
+
"region",
|
|
3941
|
+
"regret",
|
|
3942
|
+
"regular",
|
|
3943
|
+
"reject",
|
|
3944
|
+
"relax",
|
|
3945
|
+
"release",
|
|
3946
|
+
"relief",
|
|
3947
|
+
"rely",
|
|
3948
|
+
"remain",
|
|
3949
|
+
"remember",
|
|
3950
|
+
"remind",
|
|
3951
|
+
"remove",
|
|
3952
|
+
"render",
|
|
3953
|
+
"renew",
|
|
3954
|
+
"rent",
|
|
3955
|
+
"reopen",
|
|
3956
|
+
"repair",
|
|
3957
|
+
"repeat",
|
|
3958
|
+
"replace",
|
|
3959
|
+
"report",
|
|
3960
|
+
"require",
|
|
3961
|
+
"rescue",
|
|
3962
|
+
"resemble",
|
|
3963
|
+
"resist",
|
|
3964
|
+
"resource",
|
|
3965
|
+
"response",
|
|
3966
|
+
"result",
|
|
3967
|
+
"retire",
|
|
3968
|
+
"retreat",
|
|
3969
|
+
"return",
|
|
3970
|
+
"reunion",
|
|
3971
|
+
"reveal",
|
|
3972
|
+
"review",
|
|
3973
|
+
"reward",
|
|
3974
|
+
"rhythm",
|
|
3975
|
+
"rib",
|
|
3976
|
+
"ribbon",
|
|
3977
|
+
"rice",
|
|
3978
|
+
"rich",
|
|
3979
|
+
"ride",
|
|
3980
|
+
"ridge",
|
|
3981
|
+
"rifle",
|
|
3982
|
+
"right",
|
|
3983
|
+
"rigid",
|
|
3984
|
+
"ring",
|
|
3985
|
+
"riot",
|
|
3986
|
+
"ripple",
|
|
3987
|
+
"risk",
|
|
3988
|
+
"ritual",
|
|
3989
|
+
"rival",
|
|
3990
|
+
"river",
|
|
3991
|
+
"road",
|
|
3992
|
+
"roast",
|
|
3993
|
+
"robot",
|
|
3994
|
+
"robust",
|
|
3995
|
+
"rocket",
|
|
3996
|
+
"romance",
|
|
3997
|
+
"roof",
|
|
3998
|
+
"rookie",
|
|
3999
|
+
"room",
|
|
4000
|
+
"rose",
|
|
4001
|
+
"rotate",
|
|
4002
|
+
"rough",
|
|
4003
|
+
"round",
|
|
4004
|
+
"route",
|
|
4005
|
+
"royal",
|
|
4006
|
+
"rubber",
|
|
4007
|
+
"rude",
|
|
4008
|
+
"rug",
|
|
4009
|
+
"rule",
|
|
4010
|
+
"run",
|
|
4011
|
+
"runway",
|
|
4012
|
+
"rural",
|
|
4013
|
+
"sad",
|
|
4014
|
+
"saddle",
|
|
4015
|
+
"sadness",
|
|
4016
|
+
"safe",
|
|
4017
|
+
"sail",
|
|
4018
|
+
"salad",
|
|
4019
|
+
"salmon",
|
|
4020
|
+
"salon",
|
|
4021
|
+
"salt",
|
|
4022
|
+
"salute",
|
|
4023
|
+
"same",
|
|
4024
|
+
"sample",
|
|
4025
|
+
"sand",
|
|
4026
|
+
"satisfy",
|
|
4027
|
+
"satoshi",
|
|
4028
|
+
"sauce",
|
|
4029
|
+
"sausage",
|
|
4030
|
+
"save",
|
|
4031
|
+
"say",
|
|
4032
|
+
"scale",
|
|
4033
|
+
"scan",
|
|
4034
|
+
"scare",
|
|
4035
|
+
"scatter",
|
|
4036
|
+
"scene",
|
|
4037
|
+
"scheme",
|
|
4038
|
+
"school",
|
|
4039
|
+
"science",
|
|
4040
|
+
"scissors",
|
|
4041
|
+
"scorpion",
|
|
4042
|
+
"scout",
|
|
4043
|
+
"scrap",
|
|
4044
|
+
"screen",
|
|
4045
|
+
"script",
|
|
4046
|
+
"scrub",
|
|
4047
|
+
"sea",
|
|
4048
|
+
"search",
|
|
4049
|
+
"season",
|
|
4050
|
+
"seat",
|
|
4051
|
+
"second",
|
|
4052
|
+
"secret",
|
|
4053
|
+
"section",
|
|
4054
|
+
"security",
|
|
4055
|
+
"seed",
|
|
4056
|
+
"seek",
|
|
4057
|
+
"segment",
|
|
4058
|
+
"select",
|
|
4059
|
+
"sell",
|
|
4060
|
+
"seminar",
|
|
4061
|
+
"senior",
|
|
4062
|
+
"sense",
|
|
4063
|
+
"sentence",
|
|
4064
|
+
"series",
|
|
4065
|
+
"service",
|
|
4066
|
+
"session",
|
|
4067
|
+
"settle",
|
|
4068
|
+
"setup",
|
|
4069
|
+
"seven",
|
|
4070
|
+
"shadow",
|
|
4071
|
+
"shaft",
|
|
4072
|
+
"shallow",
|
|
4073
|
+
"share",
|
|
4074
|
+
"shed",
|
|
4075
|
+
"shell",
|
|
4076
|
+
"sheriff",
|
|
4077
|
+
"shield",
|
|
4078
|
+
"shift",
|
|
4079
|
+
"shine",
|
|
4080
|
+
"ship",
|
|
4081
|
+
"shiver",
|
|
4082
|
+
"shock",
|
|
4083
|
+
"shoe",
|
|
4084
|
+
"shoot",
|
|
4085
|
+
"shop",
|
|
4086
|
+
"short",
|
|
4087
|
+
"shoulder",
|
|
4088
|
+
"shove",
|
|
4089
|
+
"shrimp",
|
|
4090
|
+
"shrug",
|
|
4091
|
+
"shuffle",
|
|
4092
|
+
"shy",
|
|
4093
|
+
"sibling",
|
|
4094
|
+
"sick",
|
|
4095
|
+
"side",
|
|
4096
|
+
"siege",
|
|
4097
|
+
"sight",
|
|
4098
|
+
"sign",
|
|
4099
|
+
"silent",
|
|
4100
|
+
"silk",
|
|
4101
|
+
"silly",
|
|
4102
|
+
"silver",
|
|
4103
|
+
"similar",
|
|
4104
|
+
"simple",
|
|
4105
|
+
"since",
|
|
4106
|
+
"sing",
|
|
4107
|
+
"siren",
|
|
4108
|
+
"sister",
|
|
4109
|
+
"situate",
|
|
4110
|
+
"six",
|
|
4111
|
+
"size",
|
|
4112
|
+
"skate",
|
|
4113
|
+
"sketch",
|
|
4114
|
+
"ski",
|
|
4115
|
+
"skill",
|
|
4116
|
+
"skin",
|
|
4117
|
+
"skirt",
|
|
4118
|
+
"skull",
|
|
4119
|
+
"slab",
|
|
4120
|
+
"slam",
|
|
4121
|
+
"sleep",
|
|
4122
|
+
"slender",
|
|
4123
|
+
"slice",
|
|
4124
|
+
"slide",
|
|
4125
|
+
"slight",
|
|
4126
|
+
"slim",
|
|
4127
|
+
"slogan",
|
|
4128
|
+
"slot",
|
|
4129
|
+
"slow",
|
|
4130
|
+
"slush",
|
|
4131
|
+
"small",
|
|
4132
|
+
"smart",
|
|
4133
|
+
"smile",
|
|
4134
|
+
"smoke",
|
|
4135
|
+
"smooth",
|
|
4136
|
+
"snack",
|
|
4137
|
+
"snake",
|
|
4138
|
+
"snap",
|
|
4139
|
+
"sniff",
|
|
4140
|
+
"snow",
|
|
4141
|
+
"soap",
|
|
4142
|
+
"soccer",
|
|
4143
|
+
"social",
|
|
4144
|
+
"sock",
|
|
4145
|
+
"soda",
|
|
4146
|
+
"soft",
|
|
4147
|
+
"solar",
|
|
4148
|
+
"soldier",
|
|
4149
|
+
"solid",
|
|
4150
|
+
"solution",
|
|
4151
|
+
"solve",
|
|
4152
|
+
"someone",
|
|
4153
|
+
"song",
|
|
4154
|
+
"soon",
|
|
4155
|
+
"sorry",
|
|
4156
|
+
"sort",
|
|
4157
|
+
"soul",
|
|
4158
|
+
"sound",
|
|
4159
|
+
"soup",
|
|
4160
|
+
"source",
|
|
4161
|
+
"south",
|
|
4162
|
+
"space",
|
|
4163
|
+
"spare",
|
|
4164
|
+
"spatial",
|
|
4165
|
+
"spawn",
|
|
4166
|
+
"speak",
|
|
4167
|
+
"special",
|
|
4168
|
+
"speed",
|
|
4169
|
+
"spell",
|
|
4170
|
+
"spend",
|
|
4171
|
+
"sphere",
|
|
4172
|
+
"spice",
|
|
4173
|
+
"spider",
|
|
4174
|
+
"spike",
|
|
4175
|
+
"spin",
|
|
4176
|
+
"spirit",
|
|
4177
|
+
"split",
|
|
4178
|
+
"spoil",
|
|
4179
|
+
"sponsor",
|
|
4180
|
+
"spoon",
|
|
4181
|
+
"sport",
|
|
4182
|
+
"spot",
|
|
4183
|
+
"spray",
|
|
4184
|
+
"spread",
|
|
4185
|
+
"spring",
|
|
4186
|
+
"spy",
|
|
4187
|
+
"square",
|
|
4188
|
+
"squeeze",
|
|
4189
|
+
"squirrel",
|
|
4190
|
+
"stable",
|
|
4191
|
+
"stadium",
|
|
4192
|
+
"staff",
|
|
4193
|
+
"stage",
|
|
4194
|
+
"stairs",
|
|
4195
|
+
"stamp",
|
|
4196
|
+
"stand",
|
|
4197
|
+
"start",
|
|
4198
|
+
"state",
|
|
4199
|
+
"stay",
|
|
4200
|
+
"steak",
|
|
4201
|
+
"steel",
|
|
4202
|
+
"stem",
|
|
4203
|
+
"step",
|
|
4204
|
+
"stereo",
|
|
4205
|
+
"stick",
|
|
4206
|
+
"still",
|
|
4207
|
+
"sting",
|
|
4208
|
+
"stock",
|
|
4209
|
+
"stomach",
|
|
4210
|
+
"stone",
|
|
4211
|
+
"stool",
|
|
4212
|
+
"story",
|
|
4213
|
+
"stove",
|
|
4214
|
+
"strategy",
|
|
4215
|
+
"street",
|
|
4216
|
+
"strike",
|
|
4217
|
+
"strong",
|
|
4218
|
+
"struggle",
|
|
4219
|
+
"student",
|
|
4220
|
+
"stuff",
|
|
4221
|
+
"stumble",
|
|
4222
|
+
"style",
|
|
4223
|
+
"subject",
|
|
4224
|
+
"submit",
|
|
4225
|
+
"subway",
|
|
4226
|
+
"success",
|
|
4227
|
+
"such",
|
|
4228
|
+
"sudden",
|
|
4229
|
+
"suffer",
|
|
4230
|
+
"sugar",
|
|
4231
|
+
"suggest",
|
|
4232
|
+
"suit",
|
|
4233
|
+
"summer",
|
|
4234
|
+
"sun",
|
|
4235
|
+
"sunny",
|
|
4236
|
+
"sunset",
|
|
4237
|
+
"super",
|
|
4238
|
+
"supply",
|
|
4239
|
+
"supreme",
|
|
4240
|
+
"sure",
|
|
4241
|
+
"surface",
|
|
4242
|
+
"surge",
|
|
4243
|
+
"surprise",
|
|
4244
|
+
"surround",
|
|
4245
|
+
"survey",
|
|
4246
|
+
"suspect",
|
|
4247
|
+
"sustain",
|
|
4248
|
+
"swallow",
|
|
4249
|
+
"swamp",
|
|
4250
|
+
"swap",
|
|
4251
|
+
"swarm",
|
|
4252
|
+
"swear",
|
|
4253
|
+
"sweet",
|
|
4254
|
+
"swift",
|
|
4255
|
+
"swim",
|
|
4256
|
+
"swing",
|
|
4257
|
+
"switch",
|
|
4258
|
+
"sword",
|
|
4259
|
+
"symbol",
|
|
4260
|
+
"symptom",
|
|
4261
|
+
"syrup",
|
|
4262
|
+
"system",
|
|
4263
|
+
"table",
|
|
4264
|
+
"tackle",
|
|
4265
|
+
"tag",
|
|
4266
|
+
"tail",
|
|
4267
|
+
"talent",
|
|
4268
|
+
"talk",
|
|
4269
|
+
"tank",
|
|
4270
|
+
"tape",
|
|
4271
|
+
"target",
|
|
4272
|
+
"task",
|
|
4273
|
+
"taste",
|
|
4274
|
+
"tattoo",
|
|
4275
|
+
"taxi",
|
|
4276
|
+
"teach",
|
|
4277
|
+
"team",
|
|
4278
|
+
"tell",
|
|
4279
|
+
"ten",
|
|
4280
|
+
"tenant",
|
|
4281
|
+
"tennis",
|
|
4282
|
+
"tent",
|
|
4283
|
+
"term",
|
|
4284
|
+
"test",
|
|
4285
|
+
"text",
|
|
4286
|
+
"thank",
|
|
4287
|
+
"that",
|
|
4288
|
+
"theme",
|
|
4289
|
+
"then",
|
|
4290
|
+
"theory",
|
|
4291
|
+
"there",
|
|
4292
|
+
"they",
|
|
4293
|
+
"thing",
|
|
4294
|
+
"this",
|
|
4295
|
+
"thought",
|
|
4296
|
+
"three",
|
|
4297
|
+
"thrive",
|
|
4298
|
+
"throw",
|
|
4299
|
+
"thumb",
|
|
4300
|
+
"thunder",
|
|
4301
|
+
"ticket",
|
|
4302
|
+
"tide",
|
|
4303
|
+
"tiger",
|
|
4304
|
+
"tilt",
|
|
4305
|
+
"timber",
|
|
4306
|
+
"time",
|
|
4307
|
+
"tiny",
|
|
4308
|
+
"tip",
|
|
4309
|
+
"tired",
|
|
4310
|
+
"tissue",
|
|
4311
|
+
"title",
|
|
4312
|
+
"toast",
|
|
4313
|
+
"tobacco",
|
|
4314
|
+
"today",
|
|
4315
|
+
"toddler",
|
|
4316
|
+
"toe",
|
|
4317
|
+
"together",
|
|
4318
|
+
"toilet",
|
|
4319
|
+
"token",
|
|
4320
|
+
"tomato",
|
|
4321
|
+
"tomorrow",
|
|
4322
|
+
"tone",
|
|
4323
|
+
"tongue",
|
|
4324
|
+
"tonight",
|
|
4325
|
+
"tool",
|
|
4326
|
+
"tooth",
|
|
4327
|
+
"top",
|
|
4328
|
+
"topic",
|
|
4329
|
+
"topple",
|
|
4330
|
+
"torch",
|
|
4331
|
+
"tornado",
|
|
4332
|
+
"tortoise",
|
|
4333
|
+
"toss",
|
|
4334
|
+
"total",
|
|
4335
|
+
"tourist",
|
|
4336
|
+
"toward",
|
|
4337
|
+
"tower",
|
|
4338
|
+
"town",
|
|
4339
|
+
"toy",
|
|
4340
|
+
"track",
|
|
4341
|
+
"trade",
|
|
4342
|
+
"traffic",
|
|
4343
|
+
"tragic",
|
|
4344
|
+
"train",
|
|
4345
|
+
"transfer",
|
|
4346
|
+
"trap",
|
|
4347
|
+
"trash",
|
|
4348
|
+
"travel",
|
|
4349
|
+
"tray",
|
|
4350
|
+
"treat",
|
|
4351
|
+
"tree",
|
|
4352
|
+
"trend",
|
|
4353
|
+
"trial",
|
|
4354
|
+
"tribe",
|
|
4355
|
+
"trick",
|
|
4356
|
+
"trigger",
|
|
4357
|
+
"trim",
|
|
4358
|
+
"trip",
|
|
4359
|
+
"trophy",
|
|
4360
|
+
"trouble",
|
|
4361
|
+
"truck",
|
|
4362
|
+
"true",
|
|
4363
|
+
"truly",
|
|
4364
|
+
"trumpet",
|
|
4365
|
+
"trust",
|
|
4366
|
+
"truth",
|
|
4367
|
+
"try",
|
|
4368
|
+
"tube",
|
|
4369
|
+
"tuition",
|
|
4370
|
+
"tumble",
|
|
4371
|
+
"tuna",
|
|
4372
|
+
"tunnel",
|
|
4373
|
+
"turkey",
|
|
4374
|
+
"turn",
|
|
4375
|
+
"turtle",
|
|
4376
|
+
"twelve",
|
|
4377
|
+
"twenty",
|
|
4378
|
+
"twice",
|
|
4379
|
+
"twin",
|
|
4380
|
+
"twist",
|
|
4381
|
+
"two",
|
|
4382
|
+
"type",
|
|
4383
|
+
"typical",
|
|
4384
|
+
"ugly",
|
|
4385
|
+
"umbrella",
|
|
4386
|
+
"unable",
|
|
4387
|
+
"unaware",
|
|
4388
|
+
"uncle",
|
|
4389
|
+
"uncover",
|
|
4390
|
+
"under",
|
|
4391
|
+
"undo",
|
|
4392
|
+
"unfair",
|
|
4393
|
+
"unfold",
|
|
4394
|
+
"unhappy",
|
|
4395
|
+
"uniform",
|
|
4396
|
+
"unique",
|
|
4397
|
+
"unit",
|
|
4398
|
+
"universe",
|
|
4399
|
+
"unknown",
|
|
4400
|
+
"unlock",
|
|
4401
|
+
"until",
|
|
4402
|
+
"unusual",
|
|
4403
|
+
"unveil",
|
|
4404
|
+
"update",
|
|
4405
|
+
"upgrade",
|
|
4406
|
+
"uphold",
|
|
4407
|
+
"upon",
|
|
4408
|
+
"upper",
|
|
4409
|
+
"upset",
|
|
4410
|
+
"urban",
|
|
4411
|
+
"urge",
|
|
4412
|
+
"usage",
|
|
4413
|
+
"use",
|
|
4414
|
+
"used",
|
|
4415
|
+
"useful",
|
|
4416
|
+
"useless",
|
|
4417
|
+
"usual",
|
|
4418
|
+
"utility",
|
|
4419
|
+
"vacant",
|
|
4420
|
+
"vacuum",
|
|
4421
|
+
"vague",
|
|
4422
|
+
"valid",
|
|
4423
|
+
"valley",
|
|
4424
|
+
"valve",
|
|
4425
|
+
"van",
|
|
4426
|
+
"vanish",
|
|
4427
|
+
"vapor",
|
|
4428
|
+
"various",
|
|
4429
|
+
"vast",
|
|
4430
|
+
"vault",
|
|
4431
|
+
"vehicle",
|
|
4432
|
+
"velvet",
|
|
4433
|
+
"vendor",
|
|
4434
|
+
"venture",
|
|
4435
|
+
"venue",
|
|
4436
|
+
"verb",
|
|
4437
|
+
"verify",
|
|
4438
|
+
"version",
|
|
4439
|
+
"very",
|
|
4440
|
+
"vessel",
|
|
4441
|
+
"veteran",
|
|
4442
|
+
"viable",
|
|
4443
|
+
"vibrant",
|
|
4444
|
+
"vicious",
|
|
4445
|
+
"victory",
|
|
4446
|
+
"video",
|
|
4447
|
+
"view",
|
|
4448
|
+
"village",
|
|
4449
|
+
"vintage",
|
|
4450
|
+
"violin",
|
|
4451
|
+
"virtual",
|
|
4452
|
+
"virus",
|
|
4453
|
+
"visa",
|
|
4454
|
+
"visit",
|
|
4455
|
+
"visual",
|
|
4456
|
+
"vital",
|
|
4457
|
+
"vivid",
|
|
4458
|
+
"vocal",
|
|
4459
|
+
"voice",
|
|
4460
|
+
"void",
|
|
4461
|
+
"volcano",
|
|
4462
|
+
"volume",
|
|
4463
|
+
"vote",
|
|
4464
|
+
"voyage",
|
|
4465
|
+
"wage",
|
|
4466
|
+
"wagon",
|
|
4467
|
+
"wait",
|
|
4468
|
+
"walk",
|
|
4469
|
+
"wall",
|
|
4470
|
+
"walnut",
|
|
4471
|
+
"want",
|
|
4472
|
+
"warfare",
|
|
4473
|
+
"warm",
|
|
4474
|
+
"warrior",
|
|
4475
|
+
"wash",
|
|
4476
|
+
"wasp",
|
|
4477
|
+
"waste",
|
|
4478
|
+
"water",
|
|
4479
|
+
"wave",
|
|
4480
|
+
"way",
|
|
4481
|
+
"wealth",
|
|
4482
|
+
"weapon",
|
|
4483
|
+
"wear",
|
|
4484
|
+
"weasel",
|
|
4485
|
+
"weather",
|
|
4486
|
+
"web",
|
|
4487
|
+
"wedding",
|
|
4488
|
+
"weekend",
|
|
4489
|
+
"weird",
|
|
4490
|
+
"welcome",
|
|
4491
|
+
"west",
|
|
4492
|
+
"wet",
|
|
4493
|
+
"whale",
|
|
4494
|
+
"what",
|
|
4495
|
+
"wheat",
|
|
4496
|
+
"wheel",
|
|
4497
|
+
"when",
|
|
4498
|
+
"where",
|
|
4499
|
+
"whip",
|
|
4500
|
+
"whisper",
|
|
4501
|
+
"wide",
|
|
4502
|
+
"width",
|
|
4503
|
+
"wife",
|
|
4504
|
+
"wild",
|
|
4505
|
+
"will",
|
|
4506
|
+
"win",
|
|
4507
|
+
"window",
|
|
4508
|
+
"wine",
|
|
4509
|
+
"wing",
|
|
4510
|
+
"wink",
|
|
4511
|
+
"winner",
|
|
4512
|
+
"winter",
|
|
4513
|
+
"wire",
|
|
4514
|
+
"wisdom",
|
|
4515
|
+
"wise",
|
|
4516
|
+
"wish",
|
|
4517
|
+
"witness",
|
|
4518
|
+
"wolf",
|
|
4519
|
+
"woman",
|
|
4520
|
+
"wonder",
|
|
4521
|
+
"wood",
|
|
4522
|
+
"wool",
|
|
4523
|
+
"word",
|
|
4524
|
+
"work",
|
|
4525
|
+
"world",
|
|
4526
|
+
"worry",
|
|
4527
|
+
"worth",
|
|
4528
|
+
"wrap",
|
|
4529
|
+
"wreck",
|
|
4530
|
+
"wrestle",
|
|
4531
|
+
"wrist",
|
|
4532
|
+
"write",
|
|
4533
|
+
"wrong",
|
|
4534
|
+
"yard",
|
|
4535
|
+
"year",
|
|
4536
|
+
"yellow",
|
|
4537
|
+
"you",
|
|
4538
|
+
"young",
|
|
4539
|
+
"youth",
|
|
4540
|
+
"zebra",
|
|
4541
|
+
"zero",
|
|
4542
|
+
"zone",
|
|
4543
|
+
"zoo"
|
|
4544
|
+
];
|
|
4545
|
+
|
|
4546
|
+
// src/account/account.ts
|
|
4547
|
+
var ACCOUNT_LINK_DOMAIN = new TextEncoder().encode(
|
|
4548
|
+
"calimero.mdma.account-link.v1\0"
|
|
4549
|
+
);
|
|
4550
|
+
var ENTROPY_BITS = 256;
|
|
4551
|
+
var CHECKSUM_BITS = ENTROPY_BITS / 32;
|
|
4552
|
+
var PHRASE_WORDS = (ENTROPY_BITS + CHECKSUM_BITS) / 11;
|
|
4553
|
+
async function generateAccountRoot() {
|
|
4554
|
+
const entropy = crypto.getRandomValues(new Uint8Array(ENTROPY_BITS / 8));
|
|
4555
|
+
return withPhrase(hex(entropy), await encodePhrase(entropy));
|
|
4556
|
+
}
|
|
4557
|
+
async function accountRootFromPhrase(phrase) {
|
|
4558
|
+
const words = normalisePhrase(phrase);
|
|
4559
|
+
return withPhrase(hex(await decodePhrase(words)), words.join(" "));
|
|
4560
|
+
}
|
|
4561
|
+
async function accountRootFromSecret(secret) {
|
|
4562
|
+
fromHex(secret, "secret", 32);
|
|
4563
|
+
return {
|
|
4564
|
+
secret,
|
|
4565
|
+
publicKey: hex(await derivePublicKey(secret)),
|
|
4566
|
+
accountId: await accountForRoot(secret)
|
|
4567
|
+
};
|
|
4568
|
+
}
|
|
4569
|
+
async function signAccountLink(input) {
|
|
4570
|
+
if (!input.nonce) throw new Error("nonce is required to sign an account link");
|
|
4571
|
+
const key = await importSigningKey(input.rootSecret);
|
|
4572
|
+
const signature = new Uint8Array(
|
|
4573
|
+
await crypto.subtle.sign(
|
|
4574
|
+
"Ed25519",
|
|
4575
|
+
key,
|
|
4576
|
+
concat(ACCOUNT_LINK_DOMAIN, new TextEncoder().encode(input.nonce))
|
|
4577
|
+
)
|
|
4578
|
+
);
|
|
4579
|
+
return base64(signature);
|
|
4580
|
+
}
|
|
4581
|
+
async function withPhrase(secret, phrase) {
|
|
4582
|
+
return { ...await accountRootFromSecret(secret), phrase };
|
|
4583
|
+
}
|
|
4584
|
+
function normalisePhrase(phrase) {
|
|
4585
|
+
const words = phrase.normalize("NFKD").toLowerCase().trim().split(/\s+/);
|
|
4586
|
+
const count = words[0] === "" ? 0 : words.length;
|
|
4587
|
+
if (count !== PHRASE_WORDS) {
|
|
4588
|
+
throw new Error(
|
|
4589
|
+
`recovery phrase must be ${PHRASE_WORDS} words, got ${count}`
|
|
4590
|
+
);
|
|
4591
|
+
}
|
|
4592
|
+
return words;
|
|
4593
|
+
}
|
|
4594
|
+
async function encodePhrase(entropy) {
|
|
4595
|
+
const bits = bitsOf(entropy) + await checksumBits(entropy);
|
|
4596
|
+
const words = [];
|
|
4597
|
+
for (let i = 0; i < PHRASE_WORDS; i += 1) {
|
|
4598
|
+
const index = Number.parseInt(bits.slice(i * 11, i * 11 + 11), 2);
|
|
4599
|
+
words.push(ENGLISH_WORDLIST[index]);
|
|
4600
|
+
}
|
|
4601
|
+
return words.join(" ");
|
|
4602
|
+
}
|
|
4603
|
+
async function decodePhrase(words) {
|
|
4604
|
+
let bits = "";
|
|
4605
|
+
for (const word of words) {
|
|
4606
|
+
const index = ENGLISH_WORDLIST.indexOf(word);
|
|
4607
|
+
if (index < 0) {
|
|
4608
|
+
throw new Error(`"${word}" is not a word in the recovery phrase list`);
|
|
4609
|
+
}
|
|
4610
|
+
bits += index.toString(2).padStart(11, "0");
|
|
4611
|
+
}
|
|
4612
|
+
const entropy = new Uint8Array(ENTROPY_BITS / 8);
|
|
4613
|
+
for (let i = 0; i < entropy.length; i += 1) {
|
|
4614
|
+
entropy[i] = Number.parseInt(bits.slice(i * 8, i * 8 + 8), 2);
|
|
4615
|
+
}
|
|
4616
|
+
if (bits.slice(ENTROPY_BITS) !== await checksumBits(entropy)) {
|
|
4617
|
+
throw new Error(
|
|
4618
|
+
"recovery phrase checksum failed \u2014 check for a mistyped or transposed word"
|
|
4619
|
+
);
|
|
4620
|
+
}
|
|
4621
|
+
return entropy;
|
|
4622
|
+
}
|
|
4623
|
+
async function checksumBits(entropy) {
|
|
4624
|
+
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", entropy));
|
|
4625
|
+
return bitsOf(digest).slice(0, CHECKSUM_BITS);
|
|
4626
|
+
}
|
|
4627
|
+
function bitsOf(bytes) {
|
|
4628
|
+
let bits = "";
|
|
4629
|
+
for (const byte of bytes) bits += byte.toString(2).padStart(8, "0");
|
|
4630
|
+
return bits;
|
|
4631
|
+
}
|
|
4632
|
+
function base64(bytes) {
|
|
4633
|
+
let binary = "";
|
|
4634
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
4635
|
+
return btoa(binary);
|
|
4636
|
+
}
|
|
4637
|
+
|
|
2291
4638
|
// src/cloud/cloud-client.ts
|
|
2292
4639
|
var DEFAULT_CLOUD_BASE_URL = "https://cloud.calimero.network";
|
|
2293
4640
|
var REFRESH_HEADER = "x-mdma-session-refresh";
|
|
@@ -2531,6 +4878,93 @@ var CloudClient = class {
|
|
|
2531
4878
|
window.open(`${this.baseUrl}/disable-ha?${params.toString()}`);
|
|
2532
4879
|
}
|
|
2533
4880
|
/** Record a freshly-issued session and tell the app to persist it. */
|
|
4881
|
+
/**
|
|
4882
|
+
* Link a Calimero account to this cloud login, proving possession of its root.
|
|
4883
|
+
*
|
|
4884
|
+
* Two hops, folded into one call because they are useless apart: fetch a
|
|
4885
|
+
* single-use challenge, then sign it with the account root and post the proof.
|
|
4886
|
+
* The secret never leaves this process — only a signature over a nonce the
|
|
4887
|
+
* cloud minted does.
|
|
4888
|
+
*
|
|
4889
|
+
* This is the binding the cloud bills against. A relay does not need it to run
|
|
4890
|
+
* an intent; the cloud needs it to know whose plan a hosted node is spending,
|
|
4891
|
+
* and to sign that account back in later.
|
|
4892
|
+
*
|
|
4893
|
+
* @param rootSecret the account root's signing secret, 64 hex — from
|
|
4894
|
+
* {@link generateAccountRoot}, from a restored recovery phrase, or from a
|
|
4895
|
+
* desktop app or hardware key that already holds one.
|
|
4896
|
+
*
|
|
4897
|
+
* Idempotent for the same login. An account already linked to a *different*
|
|
4898
|
+
* cloud login is a `409`; a replayed or expired challenge is a `403`; and
|
|
4899
|
+
* exceeding the plan's account limit is a `402`.
|
|
4900
|
+
*/
|
|
4901
|
+
async linkAccount(rootSecret) {
|
|
4902
|
+
const root = await accountRootFromSecret(rootSecret);
|
|
4903
|
+
const { nonce } = await this.getAccountLinkChallenge();
|
|
4904
|
+
return this.submitAccountLink({
|
|
4905
|
+
accountId: root.accountId,
|
|
4906
|
+
rootPublicKey: root.publicKey,
|
|
4907
|
+
nonce,
|
|
4908
|
+
signature: await signAccountLink({ rootSecret, nonce })
|
|
4909
|
+
});
|
|
4910
|
+
}
|
|
4911
|
+
/**
|
|
4912
|
+
* Mint a single-use challenge for an account root to sign.
|
|
4913
|
+
*
|
|
4914
|
+
* The split half of {@link linkAccount}, for the case that call cannot serve:
|
|
4915
|
+
* a root held by a desktop app, a hardware key or an air-gapped machine, which
|
|
4916
|
+
* signs without the secret ever reaching this process. Fetch the challenge
|
|
4917
|
+
* here, have the holder sign it, then hand the proof to
|
|
4918
|
+
* {@link submitAccountLink}.
|
|
4919
|
+
*
|
|
4920
|
+
* Bound to the signed-in login and short-lived, so it is not a standing
|
|
4921
|
+
* capability if it leaks — but it IS single-use, so a challenge fetched and
|
|
4922
|
+
* abandoned is spent.
|
|
4923
|
+
*/
|
|
4924
|
+
async getAccountLinkChallenge() {
|
|
4925
|
+
const body = await this.request("GET", "/api/cloud/me/accounts/challenge");
|
|
4926
|
+
return { nonce: body.nonce, expiresAtMs: body.expires_at_ms ?? null };
|
|
4927
|
+
}
|
|
4928
|
+
/**
|
|
4929
|
+
* Post a proof assembled elsewhere. The other half of
|
|
4930
|
+
* {@link getAccountLinkChallenge}.
|
|
4931
|
+
*
|
|
4932
|
+
* `accountId` must be the account `rootPublicKey` names — the cloud refuses a
|
|
4933
|
+
* valid signature by a key that names a different account, or a caller could
|
|
4934
|
+
* prove one root and link somebody else's account. Derive both from the same
|
|
4935
|
+
* key rather than letting a user type either.
|
|
4936
|
+
*/
|
|
4937
|
+
async submitAccountLink(proof) {
|
|
4938
|
+
const body = await this.request(
|
|
4939
|
+
"POST",
|
|
4940
|
+
"/api/cloud/me/accounts",
|
|
4941
|
+
{
|
|
4942
|
+
body: {
|
|
4943
|
+
account_id: proof.accountId,
|
|
4944
|
+
root_public_key: proof.rootPublicKey,
|
|
4945
|
+
nonce: proof.nonce,
|
|
4946
|
+
signature: proof.signature
|
|
4947
|
+
}
|
|
4948
|
+
}
|
|
4949
|
+
);
|
|
4950
|
+
return {
|
|
4951
|
+
accountId: String(body.account_id ?? proof.accountId),
|
|
4952
|
+
linkedAt: body.linked_at ?? null,
|
|
4953
|
+
alreadyLinked: body.already_linked === true
|
|
4954
|
+
};
|
|
4955
|
+
}
|
|
4956
|
+
/** The accounts linked to this login, and how many the plan allows. */
|
|
4957
|
+
async getMyAccounts() {
|
|
4958
|
+
const body = await this.request("GET", "/api/cloud/me/accounts");
|
|
4959
|
+
return {
|
|
4960
|
+
accounts: (body.accounts ?? []).map((row) => ({
|
|
4961
|
+
accountId: String(row.account_id ?? ""),
|
|
4962
|
+
linkedAt: row.linked_at ?? null,
|
|
4963
|
+
hasRecoveryEnvelope: row.has_recovery_envelope === true
|
|
4964
|
+
})),
|
|
4965
|
+
limit: body.limit ?? null
|
|
4966
|
+
};
|
|
4967
|
+
}
|
|
2534
4968
|
adoptSession(body) {
|
|
2535
4969
|
this.session = {
|
|
2536
4970
|
sessionToken: body.session_token,
|
|
@@ -3010,105 +5444,6 @@ var LocalStorageTokenStore = class {
|
|
|
3010
5444
|
}
|
|
3011
5445
|
};
|
|
3012
5446
|
|
|
3013
|
-
// src/crypto/internal.ts
|
|
3014
|
-
var PKCS8_ED25519_PREFIX = new Uint8Array([
|
|
3015
|
-
48,
|
|
3016
|
-
46,
|
|
3017
|
-
2,
|
|
3018
|
-
1,
|
|
3019
|
-
0,
|
|
3020
|
-
48,
|
|
3021
|
-
5,
|
|
3022
|
-
6,
|
|
3023
|
-
3,
|
|
3024
|
-
43,
|
|
3025
|
-
101,
|
|
3026
|
-
112,
|
|
3027
|
-
4,
|
|
3028
|
-
34,
|
|
3029
|
-
4,
|
|
3030
|
-
32
|
|
3031
|
-
]);
|
|
3032
|
-
function u32le(value) {
|
|
3033
|
-
const out = new Uint8Array(4);
|
|
3034
|
-
new DataView(out.buffer).setUint32(0, value, true);
|
|
3035
|
-
return out;
|
|
3036
|
-
}
|
|
3037
|
-
function hex(bytes) {
|
|
3038
|
-
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
3039
|
-
}
|
|
3040
|
-
function fromHex(value, label, expectedBytes) {
|
|
3041
|
-
const clean = value.trim();
|
|
3042
|
-
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {
|
|
3043
|
-
throw new Error(
|
|
3044
|
-
`${label} must be ${expectedBytes * 2} hex characters, got ${clean.length}`
|
|
3045
|
-
);
|
|
3046
|
-
}
|
|
3047
|
-
const bytes = new Uint8Array(expectedBytes);
|
|
3048
|
-
for (let i = 0; i < expectedBytes; i += 1) {
|
|
3049
|
-
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
3050
|
-
}
|
|
3051
|
-
return bytes;
|
|
3052
|
-
}
|
|
3053
|
-
function u64le(value) {
|
|
3054
|
-
const out = new Uint8Array(8);
|
|
3055
|
-
new DataView(out.buffer).setBigUint64(0, BigInt(value), true);
|
|
3056
|
-
return out;
|
|
3057
|
-
}
|
|
3058
|
-
function concat(...parts) {
|
|
3059
|
-
const out = new Uint8Array(parts.reduce((total, p) => total + p.length, 0));
|
|
3060
|
-
let offset = 0;
|
|
3061
|
-
for (const part of parts) {
|
|
3062
|
-
out.set(part, offset);
|
|
3063
|
-
offset += part.length;
|
|
3064
|
-
}
|
|
3065
|
-
return out;
|
|
3066
|
-
}
|
|
3067
|
-
async function domainHash(domain, parts) {
|
|
3068
|
-
const chunks = [u64le(domain.length), domain];
|
|
3069
|
-
for (const part of parts) {
|
|
3070
|
-
chunks.push(u64le(part.length), part);
|
|
3071
|
-
}
|
|
3072
|
-
return new Uint8Array(
|
|
3073
|
-
await crypto.subtle.digest("SHA-256", concat(...chunks))
|
|
3074
|
-
);
|
|
3075
|
-
}
|
|
3076
|
-
async function importSigningKey(secretHex) {
|
|
3077
|
-
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
3078
|
-
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
3079
|
-
try {
|
|
3080
|
-
return await crypto.subtle.importKey(
|
|
3081
|
-
"pkcs8",
|
|
3082
|
-
pkcs8,
|
|
3083
|
-
{ name: "Ed25519" },
|
|
3084
|
-
false,
|
|
3085
|
-
["sign"]
|
|
3086
|
-
);
|
|
3087
|
-
} catch (cause) {
|
|
3088
|
-
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
3089
|
-
throw new Error(
|
|
3090
|
-
"this runtime has no WebCrypto Ed25519, so a warrant cannot be signed here. Node 18.4+, Safari 17+, Firefox 129+ and Chrome 137+ have it; otherwise mint the warrant with `merod account warrant`" + detail
|
|
3091
|
-
);
|
|
3092
|
-
}
|
|
3093
|
-
}
|
|
3094
|
-
async function derivePublicKey(secretHex) {
|
|
3095
|
-
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
3096
|
-
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
3097
|
-
const key = await crypto.subtle.importKey(
|
|
3098
|
-
"pkcs8",
|
|
3099
|
-
pkcs8,
|
|
3100
|
-
{ name: "Ed25519" },
|
|
3101
|
-
true,
|
|
3102
|
-
["sign"]
|
|
3103
|
-
);
|
|
3104
|
-
const jwk = await crypto.subtle.exportKey("jwk", key);
|
|
3105
|
-
const raw = jwk.x;
|
|
3106
|
-
return Uint8Array.from(
|
|
3107
|
-
atob(raw.replace(/-/g, "+").replace(/_/g, "/")),
|
|
3108
|
-
(c) => c.charCodeAt(0)
|
|
3109
|
-
);
|
|
3110
|
-
}
|
|
3111
|
-
|
|
3112
5447
|
// src/warrant/warrant.ts
|
|
3113
5448
|
var SIGN_DOMAIN = new TextEncoder().encode("calimero.warrant.v2");
|
|
3114
5449
|
var INTENT_DOMAIN = new TextEncoder().encode("calimero.warrant.intent.v1");
|
|
@@ -3422,83 +5757,6 @@ async function defaultNonceSource(deviceSecret) {
|
|
|
3422
5757
|
}
|
|
3423
5758
|
}
|
|
3424
5759
|
|
|
3425
|
-
// src/device-cert/device-cert.ts
|
|
3426
|
-
var CERT_DOMAIN = new TextEncoder().encode("calimero.device.cert.v1");
|
|
3427
|
-
var ACCOUNT_ID_DOMAIN = new TextEncoder().encode("calimero.account.genesis.v1");
|
|
3428
|
-
var DEVICE_ID_DOMAIN = new TextEncoder().encode("calimero.device.id.v1");
|
|
3429
|
-
var ACCOUNT_GENESIS_VERSION = 2;
|
|
3430
|
-
async function mintDeviceId(account, nonce) {
|
|
3431
|
-
if (nonce.length !== 16) {
|
|
3432
|
-
throw new Error(`nonce must be 16 bytes, got ${nonce.length}`);
|
|
3433
|
-
}
|
|
3434
|
-
const accountBytes = fromHex(account, "account", 32);
|
|
3435
|
-
return hex(await domainHash(DEVICE_ID_DOMAIN, [accountBytes, nonce]));
|
|
3436
|
-
}
|
|
3437
|
-
async function deviceCertPayload(input) {
|
|
3438
|
-
return domainHash(CERT_DOMAIN, [
|
|
3439
|
-
fromHex(input.account, "account", 32),
|
|
3440
|
-
fromHex(input.device, "device", 32),
|
|
3441
|
-
fromHex(input.signPublicKey, "signPublicKey", 32),
|
|
3442
|
-
fromHex(input.kemPublicKey, "kemPublicKey", 32),
|
|
3443
|
-
u32le(input.keyEpoch),
|
|
3444
|
-
u32le(input.deviceEpoch)
|
|
3445
|
-
]);
|
|
3446
|
-
}
|
|
3447
|
-
function accountProofBytes(input) {
|
|
3448
|
-
return concat(
|
|
3449
|
-
new Uint8Array([ACCOUNT_GENESIS_VERSION]),
|
|
3450
|
-
input.rootPublicKey,
|
|
3451
|
-
u32le(0),
|
|
3452
|
-
fromHex(input.account, "account", 32),
|
|
3453
|
-
fromHex(input.device, "device", 32),
|
|
3454
|
-
fromHex(input.signPublicKey, "signPublicKey", 32),
|
|
3455
|
-
fromHex(input.kemPublicKey, "kemPublicKey", 32),
|
|
3456
|
-
u32le(input.keyEpoch),
|
|
3457
|
-
u32le(input.deviceEpoch),
|
|
3458
|
-
input.signature
|
|
3459
|
-
);
|
|
3460
|
-
}
|
|
3461
|
-
async function signDeviceCert(input) {
|
|
3462
|
-
const rootPublicKey = await derivePublicKey(input.rootSecret);
|
|
3463
|
-
const account = hex(
|
|
3464
|
-
await domainHash(ACCOUNT_ID_DOMAIN, [
|
|
3465
|
-
concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey)
|
|
3466
|
-
])
|
|
3467
|
-
);
|
|
3468
|
-
const keyEpoch = 0;
|
|
3469
|
-
const payload = await deviceCertPayload({
|
|
3470
|
-
account,
|
|
3471
|
-
device: input.device,
|
|
3472
|
-
signPublicKey: input.signPublicKey,
|
|
3473
|
-
kemPublicKey: input.kemPublicKey,
|
|
3474
|
-
keyEpoch,
|
|
3475
|
-
deviceEpoch: input.deviceEpoch
|
|
3476
|
-
});
|
|
3477
|
-
const key = await importSigningKey(input.rootSecret);
|
|
3478
|
-
const signature = new Uint8Array(
|
|
3479
|
-
await crypto.subtle.sign("Ed25519", key, payload)
|
|
3480
|
-
);
|
|
3481
|
-
const credential = accountProofBytes({
|
|
3482
|
-
rootPublicKey,
|
|
3483
|
-
account,
|
|
3484
|
-
device: input.device,
|
|
3485
|
-
signPublicKey: input.signPublicKey,
|
|
3486
|
-
kemPublicKey: input.kemPublicKey,
|
|
3487
|
-
keyEpoch,
|
|
3488
|
-
deviceEpoch: input.deviceEpoch,
|
|
3489
|
-
signature
|
|
3490
|
-
});
|
|
3491
|
-
return hex(credential);
|
|
3492
|
-
}
|
|
3493
|
-
async function accountForRoot(rootSecret) {
|
|
3494
|
-
const rootPublicKey = await derivePublicKey(rootSecret);
|
|
3495
|
-
return hex(
|
|
3496
|
-
await domainHash(ACCOUNT_ID_DOMAIN, [
|
|
3497
|
-
concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey)
|
|
3498
|
-
])
|
|
3499
|
-
);
|
|
3500
|
-
}
|
|
3501
|
-
|
|
3502
5760
|
// src/namespace-op/namespace-op.ts
|
|
3503
5761
|
var SIGNED_NAMESPACE_OP_SCHEMA_VERSION = 8;
|
|
3504
5762
|
var NAMESPACE_SIGN_DOMAIN = new TextEncoder().encode("calimero.namespace.v1");
|
|
@@ -3881,6 +6139,8 @@ export {
|
|
|
3881
6139
|
WebHttpClient,
|
|
3882
6140
|
WsClient,
|
|
3883
6141
|
accountForRoot,
|
|
6142
|
+
accountRootFromPhrase,
|
|
6143
|
+
accountRootFromSecret,
|
|
3884
6144
|
buildAuthLoginUrl,
|
|
3885
6145
|
combineSignals,
|
|
3886
6146
|
compareSemver,
|
|
@@ -3905,6 +6165,7 @@ export {
|
|
|
3905
6165
|
deviceCertPayload,
|
|
3906
6166
|
discoverLocalNodes,
|
|
3907
6167
|
encodeSignedInvitation,
|
|
6168
|
+
generateAccountRoot,
|
|
3908
6169
|
generateSessionKey,
|
|
3909
6170
|
hasCap,
|
|
3910
6171
|
intentHash,
|
|
@@ -3915,6 +6176,7 @@ export {
|
|
|
3915
6176
|
nodeEndpoint,
|
|
3916
6177
|
parseAuthCallback,
|
|
3917
6178
|
probeNodeHealth,
|
|
6179
|
+
signAccountLink,
|
|
3918
6180
|
signDeviceCert,
|
|
3919
6181
|
signLoginStatement,
|
|
3920
6182
|
signMemberJoinOp,
|