eff-mnemonic 0.0.2 → 0.0.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # EFF Large Mnemonic
1
+ # EFF Mnemonic
2
2
 
3
- Convert buffers to and from a human-readable mnemonic phrase using the eff wordlists. This library was built with the purpose of generating mnemonics from passwords or private keys so that they can be easily written down on paper.
3
+ Convert buffers to and from a human-readable mnemonic phrase using eff wordlists. This library was built with the purpose of generating mnemonics from passwords or private keys so that they can be easily written down on paper.
4
4
 
5
5
  ## CLI Usage
6
6
 
@@ -9,7 +9,7 @@ You can use the cli to encode and decode secret phrases or files.
9
9
  #### Encode in interactive mode
10
10
 
11
11
  ```sh
12
- > ./cli
12
+ > npx eff-mnemonic
13
13
  🔑 # enter your secret phrase
14
14
  ┌─────────┬────────────┬───────────┬────────────┬──────────┬───────────┐
15
15
  │ (index) │ 0 │ 1 │ 2 │ 3 │ 4 │
@@ -22,7 +22,7 @@ You can use the cli to encode and decode secret phrases or files.
22
22
  #### Decode in interactive mode
23
23
 
24
24
  ```sh
25
- ./cli -d
25
+ npx eff-mnemonic -d
26
26
  🔎 bloomers triceps shoptalk travel prodigy outlast shranK
27
27
  hello world%
28
28
  ```
@@ -31,7 +31,7 @@ hello world%
31
31
 
32
32
  ```sh
33
33
  # the cli pretty prints the mnemonic if output is not redirected
34
- > echo -n "hello" | ./cli
34
+ > echo -n "hello" | npx eff-mnemonic
35
35
  ┌─────────┬───────────┬─────────┬─────────┐
36
36
  │ (index) │ 0 │ 1 │ 2 │
37
37
  ├─────────┼───────────┼─────────┼─────────┤
@@ -39,11 +39,11 @@ hello world%
39
39
  └─────────┴───────────┴─────────┴─────────┘
40
40
 
41
41
  # the cli plays nice when the output is piped
42
- > echo -n "hello" | ./cli | ./cli -d | cat
42
+ > echo -n "hello" | npx eff-mnemonic | npx eff-mnemonic -d | cat
43
43
  hello%
44
44
 
45
45
  # the cli plays nice when the output is redirected
46
- > echo -n "hello" | ./cli | ./cli -d > output.txt
46
+ > echo -n "hello" | npx eff-mnemonic | npx eff-mnemonic -d > output.txt
47
47
  ```
48
48
 
49
49
  ## Programmatic Usage
@@ -63,27 +63,25 @@ const decoded = (await mnemonicToBuffer(encoded)).toString("utf8");
63
63
  console.log(decoded); // hello world
64
64
  ```
65
65
 
66
- ### bufferToMnemonic(buffer, type)
66
+ ### bufferToMnemonic(buffer[, type])
67
67
 
68
68
  - `buffer` `<Buffer>` The buffer to encode.
69
- - `type` `<"large" | "short_1" | "short_2_0">` The eff wordlist to use, default `"large"`.
69
+ - `type` `<"large" | "short_1" | "short_2_0">` The eff wordlist to use. Default `"large"`.
70
70
  - Returns: `<string[]>` An array of mnemonic words.
71
71
 
72
72
  Encodes abuffer into a human-readable mnemonic word array from the eff wordlist.
73
73
 
74
- ### mnemonicToBuffer(buffer, type)
75
-
76
- Arguments
74
+ ### mnemonicToBuffer(words[, type])
77
75
 
78
76
  - `words` `<string[]>` An array of mnemonic words.
79
- - `type` `<"large" | "short_1" | "short_2_0">` The eff wordlist to use, default `"large"`
77
+ - `type` `<"large" | "short_1" | "short_2_0">` The eff wordlist to use. Default `"large"`
80
78
  - Returns: `<Buffer>` The decoded buffer.
81
79
 
82
80
  Decodes a mnemonic word array back into its original buffer.
83
81
 
84
82
  ## Quirks
85
83
 
86
- Internally, null characters `0x00` are used to pad the input if it's not divisible by 5. So the decoding process strips preceeding null characters before returning the output.
84
+ Internally, null characters `0x00` are used to pad the input if it's not divisible by 5 for the large list or 4 for the short lists. So the decoding process strips preceeding null characters before returning the output.
87
85
 
88
86
  #### Default behaviour
89
87
 
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import("../dist/cli.mjs");
package/dist/cli.cjs ADDED
@@ -0,0 +1,150 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ const require_mnemonic = require("./mnemonic-BUQepJt4.cjs");
24
+ let node_readline = require("node:readline");
25
+ node_readline = __toESM(node_readline);
26
+ //#region src/cli.ts
27
+ const { values } = (0, require("node:util").parseArgs)({
28
+ options: {
29
+ encode: {
30
+ type: "boolean",
31
+ short: "e",
32
+ default: true
33
+ },
34
+ decode: {
35
+ type: "boolean",
36
+ short: "d"
37
+ },
38
+ wordlist: {
39
+ type: "string",
40
+ short: "w"
41
+ }
42
+ },
43
+ tokens: true
44
+ });
45
+ const mode = values.decode ? "decode" : "encode";
46
+ if (values.wordlist === "large" || values.wordlist === "short_1" || values.wordlist === "short_2_0") values.wordlist;
47
+ else if (values.wordlist) {
48
+ console.error(`Error: Invalid value for wordlist, must be "large", "short_1", or "short_2_0"`);
49
+ process.exit(1);
50
+ }
51
+ /** Captures input to encode without printing it on screen */
52
+ function captureEncodeInput() {
53
+ const query = "🔑 ";
54
+ return new Promise((resolve) => {
55
+ const rl = node_readline.default.createInterface({
56
+ input: process.stdin,
57
+ output: process.stderr
58
+ });
59
+ const stdin = process.stdin;
60
+ stdin.setRawMode(true);
61
+ stdin.resume();
62
+ let password = "";
63
+ process.stderr.write(query);
64
+ const onData = (char) => {
65
+ const charStr = char.toString("utf8");
66
+ let end = false;
67
+ let exitCode;
68
+ switch (charStr) {
69
+ case "\n":
70
+ case "\r":
71
+ case "":
72
+ resolve(password);
73
+ end = true;
74
+ break;
75
+ case "":
76
+ exitCode = 130;
77
+ process.exit(130);
78
+ end = true;
79
+ break;
80
+ case "":
81
+ case "\b":
82
+ if (password.length > 0) password = password.slice(0, -1);
83
+ break;
84
+ default:
85
+ if (charStr.charCodeAt(0) >= 32) password += charStr;
86
+ break;
87
+ }
88
+ if (end) {
89
+ stdin.removeListener("data", onData);
90
+ stdin.setRawMode(false);
91
+ rl.close();
92
+ if (exitCode) process.exit(exitCode);
93
+ } else {
94
+ node_readline.default.clearLine(process.stderr, 0);
95
+ node_readline.default.cursorTo(process.stderr, 0);
96
+ process.stderr.write(query);
97
+ }
98
+ };
99
+ stdin.on("data", onData);
100
+ });
101
+ }
102
+ /** Captures input to decode transparently */
103
+ function captureDecodeInput() {
104
+ const query = "🔎 ";
105
+ return new Promise((resolve) => {
106
+ const rl = node_readline.default.createInterface({
107
+ input: process.stdin,
108
+ output: process.stdout
109
+ });
110
+ rl.question(query, (value) => {
111
+ rl.close();
112
+ resolve(value);
113
+ });
114
+ });
115
+ }
116
+ async function main() {
117
+ let input;
118
+ if (process.stdin.isTTY) {
119
+ let text;
120
+ if (mode === "encode") text = await captureEncodeInput();
121
+ else text = await captureDecodeInput();
122
+ input = Buffer.from(text, "utf8");
123
+ } else {
124
+ const chunks = [];
125
+ for await (const chunk of process.stdin) chunks.push(chunk);
126
+ input = Buffer.concat(chunks);
127
+ }
128
+ if (!input) {
129
+ console.error("Error: No input provided");
130
+ process.exit(1);
131
+ }
132
+ if (mode === "encode") {
133
+ const words = await require_mnemonic.bufferToMnemonic(input);
134
+ if (process.stdout.isTTY) {
135
+ const table = words.reduce((acc, it, i) => {
136
+ const j = Math.floor(i / 5);
137
+ const k = i % 5;
138
+ acc[j] ??= [];
139
+ acc[j][k] = it;
140
+ return acc;
141
+ }, []);
142
+ console.table(table);
143
+ } else process.stdout.write(words.join(" "));
144
+ } else {
145
+ const decoded = await require_mnemonic.mnemonicToBuffer(input.toString("utf8").replace(/[\s\t\-\_\,\:\;\.\n\'\"|\\]+/g, " ").trim().split(" "));
146
+ process.stdout.write(decoded);
147
+ }
148
+ }
149
+ main();
150
+ //#endregion
package/dist/cli.d.cts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/cli.mjs ADDED
@@ -0,0 +1,135 @@
1
+ import { n as init_mnemonic, p as __commonJSMin, r as mnemonicToBuffer, t as bufferToMnemonic } from "./mnemonic-JeCBHZim.mjs";
2
+ import readline from "node:readline";
3
+ import { parseArgs } from "node:util";
4
+ //#region src/cli.ts
5
+ var require_cli = /* @__PURE__ */ __commonJSMin((() => {
6
+ init_mnemonic();
7
+ const { values } = parseArgs({
8
+ options: {
9
+ encode: {
10
+ type: "boolean",
11
+ short: "e",
12
+ default: true
13
+ },
14
+ decode: {
15
+ type: "boolean",
16
+ short: "d"
17
+ },
18
+ wordlist: {
19
+ type: "string",
20
+ short: "w"
21
+ }
22
+ },
23
+ tokens: true
24
+ });
25
+ const mode = values.decode ? "decode" : "encode";
26
+ if (values.wordlist === "large" || values.wordlist === "short_1" || values.wordlist === "short_2_0") values.wordlist;
27
+ else if (values.wordlist) {
28
+ console.error(`Error: Invalid value for wordlist, must be "large", "short_1", or "short_2_0"`);
29
+ process.exit(1);
30
+ }
31
+ /** Captures input to encode without printing it on screen */
32
+ function captureEncodeInput() {
33
+ const query = "🔑 ";
34
+ return new Promise((resolve) => {
35
+ const rl = readline.createInterface({
36
+ input: process.stdin,
37
+ output: process.stderr
38
+ });
39
+ const stdin = process.stdin;
40
+ stdin.setRawMode(true);
41
+ stdin.resume();
42
+ let password = "";
43
+ process.stderr.write(query);
44
+ const onData = (char) => {
45
+ const charStr = char.toString("utf8");
46
+ let end = false;
47
+ let exitCode;
48
+ switch (charStr) {
49
+ case "\n":
50
+ case "\r":
51
+ case "":
52
+ resolve(password);
53
+ end = true;
54
+ break;
55
+ case "":
56
+ exitCode = 130;
57
+ process.exit(130);
58
+ end = true;
59
+ break;
60
+ case "":
61
+ case "\b":
62
+ if (password.length > 0) password = password.slice(0, -1);
63
+ break;
64
+ default:
65
+ if (charStr.charCodeAt(0) >= 32) password += charStr;
66
+ break;
67
+ }
68
+ if (end) {
69
+ stdin.removeListener("data", onData);
70
+ stdin.setRawMode(false);
71
+ rl.close();
72
+ if (exitCode) process.exit(exitCode);
73
+ } else {
74
+ readline.clearLine(process.stderr, 0);
75
+ readline.cursorTo(process.stderr, 0);
76
+ process.stderr.write(query);
77
+ }
78
+ };
79
+ stdin.on("data", onData);
80
+ });
81
+ }
82
+ /** Captures input to decode transparently */
83
+ function captureDecodeInput() {
84
+ const query = "🔎 ";
85
+ return new Promise((resolve) => {
86
+ const rl = readline.createInterface({
87
+ input: process.stdin,
88
+ output: process.stdout
89
+ });
90
+ rl.question(query, (value) => {
91
+ rl.close();
92
+ resolve(value);
93
+ });
94
+ });
95
+ }
96
+ async function main() {
97
+ let input;
98
+ if (process.stdin.isTTY) {
99
+ let text;
100
+ if (mode === "encode") text = await captureEncodeInput();
101
+ else text = await captureDecodeInput();
102
+ input = Buffer.from(text, "utf8");
103
+ } else {
104
+ const chunks = [];
105
+ for await (const chunk of process.stdin) chunks.push(chunk);
106
+ input = Buffer.concat(chunks);
107
+ }
108
+ if (!input) {
109
+ console.error("Error: No input provided");
110
+ process.exit(1);
111
+ }
112
+ if (mode === "encode") {
113
+ const words = await bufferToMnemonic(input);
114
+ if (process.stdout.isTTY) {
115
+ const table = words.reduce((acc, it, i) => {
116
+ const j = Math.floor(i / 5);
117
+ const k = i % 5;
118
+ acc[j] ??= [];
119
+ acc[j][k] = it;
120
+ return acc;
121
+ }, []);
122
+ console.table(table);
123
+ } else process.stdout.write(words.join(" "));
124
+ } else {
125
+ const decoded = await mnemonicToBuffer(input.toString("utf8").replace(/[\s\t\-\_\,\:\;\.\n\'\"|\\]+/g, " ").trim().split(" "));
126
+ process.stdout.write(decoded);
127
+ }
128
+ }
129
+ main();
130
+ }));
131
+ //#endregion
132
+ export default require_cli();
133
+ export {};
134
+
135
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import readline from \"node:readline\";\nimport { parseArgs } from \"node:util\";\nimport { EffWordListType } from \"./data\";\nimport { bufferToMnemonic, mnemonicToBuffer } from \"./mnemonic\";\n\nconst { values } = parseArgs({\n options: {\n encode: { type: \"boolean\", short: \"e\", default: true },\n decode: { type: \"boolean\", short: \"d\" },\n wordlist: { type: \"string\", short: \"w\" },\n },\n tokens: true,\n});\n\n// determine mode\nconst mode = values.decode ? \"decode\" : \"encode\";\n\n// determine wordlist\nlet wordlist: EffWordListType;\nif (\n values.wordlist === \"large\" ||\n values.wordlist === \"short_1\" ||\n values.wordlist === \"short_2_0\"\n) {\n wordlist = values.wordlist;\n} else if (values.wordlist) {\n console.error(\n `Error: Invalid value for wordlist, must be \"large\", \"short_1\", or \"short_2_0\"`,\n );\n process.exit(1);\n}\n\n/** Captures input to encode without printing it on screen */\nfunction captureEncodeInput(): Promise<string> {\n const query = \"🔑 \";\n return new Promise((resolve) => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr, // write ui to stderr to keep stdout clear\n });\n\n const stdin = process.stdin;\n stdin.setRawMode(true);\n stdin.resume();\n\n let password = \"\";\n process.stderr.write(query);\n\n const onData = (char: Buffer) => {\n const charStr = char.toString(\"utf8\");\n\n let end = false;\n let exitCode;\n switch (charStr) {\n case \"\\n\":\n case \"\\r\":\n case \"\\u0004\": // ctrl+d\n resolve(password);\n end = true;\n break;\n case \"\\u0003\": // ctrl+c\n exitCode = 130;\n process.exit(130);\n end = true;\n break;\n case \"\\u007f\": // backspace\n case \"\\b\":\n if (password.length > 0) {\n password = password.slice(0, -1);\n }\n break;\n default:\n if (charStr.charCodeAt(0) >= 32) {\n password += charStr;\n }\n break;\n }\n\n if (end) {\n stdin.removeListener(\"data\", onData);\n stdin.setRawMode(false);\n rl.close();\n\n if (exitCode) {\n process.exit(exitCode);\n }\n } else {\n readline.clearLine(process.stderr, 0);\n readline.cursorTo(process.stderr, 0);\n process.stderr.write(query);\n }\n };\n\n stdin.on(\"data\", onData);\n });\n}\n\n/** Captures input to decode transparently */\nfunction captureDecodeInput(): Promise<string> {\n const query = \"🔎 \";\n return new Promise((resolve) => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n rl.question(query, (value) => {\n rl.close();\n resolve(value);\n });\n });\n}\n\nasync function main(): Promise<void> {\n let input;\n\n // capture tty input\n if (process.stdin.isTTY) {\n let text;\n if (mode === \"encode\") {\n text = await captureEncodeInput();\n } else {\n text = await captureDecodeInput();\n }\n\n input = Buffer.from(text, \"utf8\");\n }\n\n // capture piped input\n else {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk);\n }\n\n input = Buffer.concat(chunks);\n }\n\n if (!input) {\n console.error(\"Error: No input provided\");\n process.exit(1);\n }\n\n // handle encode or decode\n if (mode === \"encode\") {\n // encode mnemonic\n const words = await bufferToMnemonic(input);\n\n // handle tty output\n if (process.stdout.isTTY) {\n // pretty format\n const table = words.reduce((acc, it, i) => {\n const j = Math.floor(i / 5);\n const k = i % 5;\n acc[j] ??= [];\n acc[j][k] = it;\n\n return acc;\n }, [] as string[][]);\n\n // print table\n console.table(table);\n } else {\n // write directly to stdout\n process.stdout.write(words.join(\" \"));\n }\n } else {\n // sanitize and parse input\n const words = input\n .toString(\"utf8\")\n .replace(/[\\s\\t\\-\\_\\,\\:\\;\\.\\n\\'\\\"|\\\\]+/g, \" \")\n .trim()\n .split(\" \");\n\n // decode mnemonic\n const decoded = await mnemonicToBuffer(words);\n\n // write directly to stdout so it can be redirected\n process.stdout.write(decoded);\n }\n}\n\nvoid main();\n"],"mappings":";;;;;eAG+D;CAE/D,MAAM,EAAE,WAAW,UAAU;EAC3B,SAAS;GACP,QAAQ;IAAE,MAAM;IAAW,OAAO;IAAK,SAAS;GAAK;GACrD,QAAQ;IAAE,MAAM;IAAW,OAAO;GAAI;GACtC,UAAU;IAAE,MAAM;IAAU,OAAO;GAAI;EACzC;EACA,QAAQ;CACV,CAAC;CAGD,MAAM,OAAO,OAAO,SAAS,WAAW;CAIxC,IACE,OAAO,aAAa,WACpB,OAAO,aAAa,aACpB,OAAO,aAAa,aAEpB,OAAkB;MACb,IAAI,OAAO,UAAU;EAC1B,QAAQ,MACN,+EACF;EACA,QAAQ,KAAK,CAAC;CAChB;;CAGA,SAAS,qBAAsC;EAC7C,MAAM,QAAQ;EACd,OAAO,IAAI,SAAS,YAAY;GAC9B,MAAM,KAAK,SAAS,gBAAgB;IAClC,OAAO,QAAQ;IACf,QAAQ,QAAQ;GAClB,CAAC;GAED,MAAM,QAAQ,QAAQ;GACtB,MAAM,WAAW,IAAI;GACrB,MAAM,OAAO;GAEb,IAAI,WAAW;GACf,QAAQ,OAAO,MAAM,KAAK;GAE1B,MAAM,UAAU,SAAiB;IAC/B,MAAM,UAAU,KAAK,SAAS,MAAM;IAEpC,IAAI,MAAM;IACV,IAAI;IACJ,QAAQ,SAAR;KACE,KAAK;KACL,KAAK;KACL,KAAK;MACH,QAAQ,QAAQ;MAChB,MAAM;MACN;KACF,KAAK;MACH,WAAW;MACX,QAAQ,KAAK,GAAG;MAChB,MAAM;MACN;KACF,KAAK;KACL,KAAK;MACH,IAAI,SAAS,SAAS,GACpB,WAAW,SAAS,MAAM,GAAG,EAAE;MAEjC;KACF;MACE,IAAI,QAAQ,WAAW,CAAC,KAAK,IAC3B,YAAY;MAEd;IACJ;IAEA,IAAI,KAAK;KACP,MAAM,eAAe,QAAQ,MAAM;KACnC,MAAM,WAAW,KAAK;KACtB,GAAG,MAAM;KAET,IAAI,UACF,QAAQ,KAAK,QAAQ;IAEzB,OAAO;KACL,SAAS,UAAU,QAAQ,QAAQ,CAAC;KACpC,SAAS,SAAS,QAAQ,QAAQ,CAAC;KACnC,QAAQ,OAAO,MAAM,KAAK;IAC5B;GACF;GAEA,MAAM,GAAG,QAAQ,MAAM;EACzB,CAAC;CACH;;CAGA,SAAS,qBAAsC;EAC7C,MAAM,QAAQ;EACd,OAAO,IAAI,SAAS,YAAY;GAC9B,MAAM,KAAK,SAAS,gBAAgB;IAClC,OAAO,QAAQ;IACf,QAAQ,QAAQ;GAClB,CAAC;GAED,GAAG,SAAS,QAAQ,UAAU;IAC5B,GAAG,MAAM;IACT,QAAQ,KAAK;GACf,CAAC;EACH,CAAC;CACH;CAEA,eAAe,OAAsB;EACnC,IAAI;EAGJ,IAAI,QAAQ,MAAM,OAAO;GACvB,IAAI;GACJ,IAAI,SAAS,UACX,OAAO,MAAM,mBAAmB;QAEhC,OAAO,MAAM,mBAAmB;GAGlC,QAAQ,OAAO,KAAK,MAAM,MAAM;EAClC,OAGK;GACH,MAAM,SAAmB,CAAC;GAC1B,WAAW,MAAM,SAAS,QAAQ,OAChC,OAAO,KAAK,KAAK;GAGnB,QAAQ,OAAO,OAAO,MAAM;EAC9B;EAEA,IAAI,CAAC,OAAO;GACV,QAAQ,MAAM,0BAA0B;GACxC,QAAQ,KAAK,CAAC;EAChB;EAGA,IAAI,SAAS,UAAU;GAErB,MAAM,QAAQ,MAAM,iBAAiB,KAAK;GAG1C,IAAI,QAAQ,OAAO,OAAO;IAExB,MAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,MAAM;KACzC,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;KAC1B,MAAM,IAAI,IAAI;KACd,IAAI,OAAO,CAAC;KACZ,IAAI,EAAE,CAAC,KAAK;KAEZ,OAAO;IACT,GAAG,CAAC,CAAe;IAGnB,QAAQ,MAAM,KAAK;GACrB,OAEE,QAAQ,OAAO,MAAM,MAAM,KAAK,GAAG,CAAC;EAExC,OAAO;GASL,MAAM,UAAU,MAAM,iBAPR,MACX,SAAS,MAAM,CAAC,CAChB,QAAQ,iCAAiC,GAAG,CAAC,CAC7C,KAAK,CAAC,CACN,MAAM,GAGkC,CAAC;GAG5C,QAAQ,OAAO,MAAM,OAAO;EAC9B;CACF;CAEA,KAAU"}
package/dist/index.cjs CHANGED
@@ -1,88 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- let node_fs_promises = require("node:fs/promises");
3
- //#region src/base-index.ts
4
- function oneToZeroBaseIndex(string) {
5
- if (!/^[1-9]*$/.test(string)) throw new TypeError(`Input "${string}" contains characters other than 1-9`);
6
- return string.replace(/\d/g, (d) => String(Number(d) - 1));
7
- }
8
- function zeroToOneBaseIndex(string) {
9
- if (!/^[0-8]*$/.test(string)) throw new TypeError(`Input "${string}" contains characters other than 0-8`);
10
- return string.replace(/\d/g, (d) => String(Number(d) + 1));
11
- }
12
- //#endregion
13
- //#region src/data.ts
14
- const numberToWordMapByType = /* @__PURE__ */ new Map();
15
- const wordToNumberMapByType = /* @__PURE__ */ new Map();
16
- const getEffNumberToWordMap = async (type) => {
17
- let map = numberToWordMapByType.get(type);
18
- if (!map) {
19
- if (type !== "large" && type !== "short_1" && type !== "short_2_0") throw new TypeError(`Invalid type "${type}"`);
20
- const file = await (0, node_fs_promises.readFile)(__dirname + `/../data/eff_wordlist_${type}.txt`, "utf8");
21
- map = new Map(file.split("\n").map((it) => it.split(" ")).map(([k, v]) => [oneToZeroBaseIndex(k), v]));
22
- numberToWordMapByType.set(type, map);
23
- }
24
- return map;
25
- };
26
- const getEffWordToNumberMap = async (type) => {
27
- let map = wordToNumberMapByType.get(type);
28
- if (!map) {
29
- const numberToWordMap = await getEffNumberToWordMap(type);
30
- map = new Map(numberToWordMap.entries().map(([k, v]) => [v, k]));
31
- wordToNumberMapByType.set(type, map);
32
- }
33
- return map;
34
- };
35
- const clearEffCache = () => {
36
- numberToWordMapByType.clear();
37
- wordToNumberMapByType.clear();
38
- };
39
- //#endregion
40
- //#region src/parse-big-int.ts
41
- function parseBigInt(string, radix) {
42
- if (radix < 2 || radix > 36) throw new TypeError("Radix must be between 2 and 36");
43
- const bigRadix = BigInt(radix);
44
- let result = 0n;
45
- for (const char of string) {
46
- const digit = parseInt(char, radix);
47
- if (isNaN(digit)) throw new TypeError(`Invalid character "${char}" for radix ${radix}`);
48
- result = result * bigRadix + BigInt(digit);
49
- }
50
- return result;
51
- }
52
- //#endregion
53
- //#region src/mnemonic.ts
54
- async function bufferToMnemonic(buffer, type = "large") {
55
- if (!buffer.length) return [];
56
- const numberToWordMap = await getEffNumberToWordMap(type);
57
- const base6 = BigInt("0x" + buffer.toString("hex")).toString(6);
58
- const rolls = type === "large" ? 5 : 4;
59
- const base6PaddedLength = Math.ceil(base6.length / rolls) * rolls;
60
- return (base6.padStart(base6PaddedLength, "0").match(new RegExp(`.{1,${rolls}}`, "g")) ?? []).map((chunk) => {
61
- const word = numberToWordMap.get(chunk);
62
- if (!word) {
63
- const sequence = zeroToOneBaseIndex(chunk);
64
- throw TypeError(`Sequence "${sequence}" not in ${type} list`);
65
- }
66
- return word;
67
- });
68
- }
69
- async function mnemonicToBuffer(words, type = "large") {
70
- if (!words.length) return Buffer.alloc(0);
71
- const wordToBase6Map = await getEffWordToNumberMap(type);
72
- let hex = parseBigInt(words.map((word) => {
73
- const chunk = wordToBase6Map.get(word.toLowerCase());
74
- if (!chunk) throw TypeError(`Word "${word}" not ${type} list`);
75
- return chunk;
76
- }).join(""), 6).toString(16);
77
- if (hex.length % 2 !== 0) hex = "0" + hex;
78
- return Buffer.from(hex, "hex");
79
- }
80
- //#endregion
81
- exports.bufferToMnemonic = bufferToMnemonic;
82
- exports.clearEffCache = clearEffCache;
83
- exports.getEffNumberToWordMap = getEffNumberToWordMap;
84
- exports.getEffWordToNumberMap = getEffWordToNumberMap;
85
- exports.mnemonicToBuffer = mnemonicToBuffer;
86
- exports.oneToZeroBaseIndex = oneToZeroBaseIndex;
87
- exports.parseBigInt = parseBigInt;
88
- exports.zeroToOneBaseIndex = zeroToOneBaseIndex;
2
+ const require_mnemonic = require("./mnemonic-BUQepJt4.cjs");
3
+ exports.bufferToMnemonic = require_mnemonic.bufferToMnemonic;
4
+ exports.clearEffCache = require_mnemonic.clearEffCache;
5
+ exports.getEffNumberToWordMap = require_mnemonic.getEffNumberToWordMap;
6
+ exports.getEffWordToNumberMap = require_mnemonic.getEffWordToNumberMap;
7
+ exports.mnemonicToBuffer = require_mnemonic.mnemonicToBuffer;
8
+ exports.oneToZeroBaseIndex = require_mnemonic.oneToZeroBaseIndex;
9
+ exports.parseBigInt = require_mnemonic.parseBigInt;
10
+ exports.zeroToOneBaseIndex = require_mnemonic.zeroToOneBaseIndex;
package/dist/index.mjs CHANGED
@@ -1,88 +1,9 @@
1
- import path from "node:path";
2
- import { fileURLToPath } from "node:url";
3
- import { readFile } from "node:fs/promises";
4
- //#region src/base-index.ts
5
- function oneToZeroBaseIndex(string) {
6
- if (!/^[1-9]*$/.test(string)) throw new TypeError(`Input "${string}" contains characters other than 1-9`);
7
- return string.replace(/\d/g, (d) => String(Number(d) - 1));
8
- }
9
- function zeroToOneBaseIndex(string) {
10
- if (!/^[0-8]*$/.test(string)) throw new TypeError(`Input "${string}" contains characters other than 0-8`);
11
- return string.replace(/\d/g, (d) => String(Number(d) + 1));
12
- }
13
- //#endregion
14
- //#region node_modules/tsdown/esm-shims.js
15
- const getFilename = () => fileURLToPath(import.meta.url);
16
- const getDirname = () => path.dirname(getFilename());
17
- const __dirname = /* @__PURE__ */ getDirname();
18
- //#endregion
19
- //#region src/data.ts
20
- const numberToWordMapByType = /* @__PURE__ */ new Map();
21
- const wordToNumberMapByType = /* @__PURE__ */ new Map();
22
- const getEffNumberToWordMap = async (type) => {
23
- let map = numberToWordMapByType.get(type);
24
- if (!map) {
25
- if (type !== "large" && type !== "short_1" && type !== "short_2_0") throw new TypeError(`Invalid type "${type}"`);
26
- const file = await readFile(__dirname + `/../data/eff_wordlist_${type}.txt`, "utf8");
27
- map = new Map(file.split("\n").map((it) => it.split(" ")).map(([k, v]) => [oneToZeroBaseIndex(k), v]));
28
- numberToWordMapByType.set(type, map);
29
- }
30
- return map;
31
- };
32
- const getEffWordToNumberMap = async (type) => {
33
- let map = wordToNumberMapByType.get(type);
34
- if (!map) {
35
- const numberToWordMap = await getEffNumberToWordMap(type);
36
- map = new Map(numberToWordMap.entries().map(([k, v]) => [v, k]));
37
- wordToNumberMapByType.set(type, map);
38
- }
39
- return map;
40
- };
41
- const clearEffCache = () => {
42
- numberToWordMapByType.clear();
43
- wordToNumberMapByType.clear();
44
- };
45
- //#endregion
46
- //#region src/parse-big-int.ts
47
- function parseBigInt(string, radix) {
48
- if (radix < 2 || radix > 36) throw new TypeError("Radix must be between 2 and 36");
49
- const bigRadix = BigInt(radix);
50
- let result = 0n;
51
- for (const char of string) {
52
- const digit = parseInt(char, radix);
53
- if (isNaN(digit)) throw new TypeError(`Invalid character "${char}" for radix ${radix}`);
54
- result = result * bigRadix + BigInt(digit);
55
- }
56
- return result;
57
- }
58
- //#endregion
59
- //#region src/mnemonic.ts
60
- async function bufferToMnemonic(buffer, type = "large") {
61
- if (!buffer.length) return [];
62
- const numberToWordMap = await getEffNumberToWordMap(type);
63
- const base6 = BigInt("0x" + buffer.toString("hex")).toString(6);
64
- const rolls = type === "large" ? 5 : 4;
65
- const base6PaddedLength = Math.ceil(base6.length / rolls) * rolls;
66
- return (base6.padStart(base6PaddedLength, "0").match(new RegExp(`.{1,${rolls}}`, "g")) ?? []).map((chunk) => {
67
- const word = numberToWordMap.get(chunk);
68
- if (!word) {
69
- const sequence = zeroToOneBaseIndex(chunk);
70
- throw TypeError(`Sequence "${sequence}" not in ${type} list`);
71
- }
72
- return word;
73
- });
74
- }
75
- async function mnemonicToBuffer(words, type = "large") {
76
- if (!words.length) return Buffer.alloc(0);
77
- const wordToBase6Map = await getEffWordToNumberMap(type);
78
- let hex = parseBigInt(words.map((word) => {
79
- const chunk = wordToBase6Map.get(word.toLowerCase());
80
- if (!chunk) throw TypeError(`Word "${word}" not ${type} list`);
81
- return chunk;
82
- }).join(""), 6).toString(16);
83
- if (hex.length % 2 !== 0) hex = "0" + hex;
84
- return Buffer.from(hex, "hex");
85
- }
1
+ import { a as parseBigInt, c as getEffWordToNumberMap, d as oneToZeroBaseIndex, f as zeroToOneBaseIndex, i as init_parse_big_int, l as init_data, n as init_mnemonic, o as clearEffCache, r as mnemonicToBuffer, s as getEffNumberToWordMap, t as bufferToMnemonic, u as init_base_index } from "./mnemonic-JeCBHZim.mjs";
2
+ //#region src/index.ts
3
+ init_base_index();
4
+ init_data();
5
+ init_mnemonic();
6
+ init_parse_big_int();
86
7
  //#endregion
87
8
  export { bufferToMnemonic, clearEffCache, getEffNumberToWordMap, getEffWordToNumberMap, mnemonicToBuffer, oneToZeroBaseIndex, parseBigInt, zeroToOneBaseIndex };
88
9
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/base-index.ts","../node_modules/tsdown/esm-shims.js","../src/data.ts","../src/parse-big-int.ts","../src/mnemonic.ts"],"sourcesContent":["export function oneToZeroBaseIndex(string: string) {\n if (!/^[1-9]*$/.test(string)) {\n throw new TypeError(`Input \"${string}\" contains characters other than 1-9`);\n }\n\n return string.replace(/\\d/g, (d) => String(Number(d) - 1));\n}\n\nexport function zeroToOneBaseIndex(string: string) {\n if (!/^[0-8]*$/.test(string)) {\n throw new TypeError(`Input \"${string}\" contains characters other than 0-8`);\n }\n\n return string.replace(/\\d/g, (d) => String(Number(d) + 1));\n}\n","// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import { readFile } from \"node:fs/promises\";\nimport { oneToZeroBaseIndex } from \"./base-index\";\n\nconst numberToWordMapByType = new Map<EffWordListType, EffWordMap>();\nconst wordToNumberMapByType = new Map<EffWordListType, EffWordMap>();\n\nexport type EffWordListType = \"large\" | \"short_1\" | \"short_2_0\";\nexport type EffWordMap = Map<string, string>;\n\nexport const getEffNumberToWordMap = async (type: EffWordListType) => {\n let map = numberToWordMapByType.get(type);\n\n // load map from file if already not loaded\n if (!map) {\n if (type !== \"large\" && type !== \"short_1\" && type !== \"short_2_0\") {\n throw new TypeError(`Invalid type \"${type}\"`);\n }\n\n const file = await readFile(\n __dirname + `/../data/eff_wordlist_${type}.txt`,\n \"utf8\",\n );\n\n // parse wordlist and build a map\n // NOTE: the dice rolls use numbers from 1 to 6, we convert this to a\n // zero based index or a base6 number\n map = new Map(\n file\n .split(\"\\n\")\n .map((it) => it.split(\"\\t\") as [string, string])\n .map(([k, v]) => [oneToZeroBaseIndex(k), v]),\n );\n\n // cache map\n numberToWordMapByType.set(type, map);\n }\n\n return map;\n};\n\nexport const getEffWordToNumberMap = async (type: EffWordListType) => {\n let map = wordToNumberMapByType.get(type);\n\n // load map from file if already not loaded\n if (!map) {\n const numberToWordMap = await getEffNumberToWordMap(type);\n\n // invert number to word map\n map = new Map(numberToWordMap.entries().map(([k, v]) => [v, k]));\n\n // cache map\n wordToNumberMapByType.set(type, map);\n }\n\n return map;\n};\n\nexport const clearEffCache = () => {\n numberToWordMapByType.clear();\n wordToNumberMapByType.clear();\n};\n","export function parseBigInt(string: string, radix: number) {\n if (radix < 2 || radix > 36) {\n throw new TypeError(\"Radix must be between 2 and 36\");\n }\n\n const bigRadix = BigInt(radix);\n\n let result = 0n;\n for (const char of string) {\n const digit = parseInt(char, radix);\n\n if (isNaN(digit)) {\n throw new TypeError(`Invalid character \"${char}\" for radix ${radix}`);\n }\n\n result = result * bigRadix + BigInt(digit);\n }\n\n return result;\n}\n","import { zeroToOneBaseIndex } from \"./base-index\";\nimport {\n EffWordListType,\n getEffNumberToWordMap,\n getEffWordToNumberMap,\n} from \"./data\";\nimport { parseBigInt } from \"./parse-big-int\";\n\nexport async function bufferToMnemonic(\n buffer: Buffer,\n type: EffWordListType = \"large\",\n) {\n // handle empty input\n if (!buffer.length) {\n return [];\n }\n\n const numberToWordMap = await getEffNumberToWordMap(type);\n const bigint = BigInt(\"0x\" + buffer.toString(\"hex\"));\n const base6 = bigint.toString(6);\n\n // pad string to ensure length is a multiple of number of dice rolls\n const rolls = type === \"large\" ? 5 : 4;\n const base6PaddedLength = Math.ceil(base6.length / rolls) * rolls;\n const base6Padded = base6.padStart(base6PaddedLength, \"0\");\n\n // split base6 string into chunks and map to words\n const base6Chunks = base6Padded.match(new RegExp(`.{1,${rolls}}`, \"g\")) ?? [];\n return base6Chunks.map((chunk) => {\n const word = numberToWordMap.get(chunk);\n if (!word) {\n const sequence = zeroToOneBaseIndex(chunk);\n throw TypeError(`Sequence \"${sequence}\" not in ${type} list`);\n }\n return word;\n });\n}\n\nexport async function mnemonicToBuffer(\n words: string[],\n type: EffWordListType = \"large\",\n) {\n // handle empty input\n if (!words.length) {\n return Buffer.alloc(0);\n }\n\n const wordToBase6Map = await getEffWordToNumberMap(type);\n const base6Chunks = words.map((word) => {\n const chunk = wordToBase6Map.get(word.toLowerCase());\n if (!chunk) {\n throw TypeError(`Word \"${word}\" not ${type} list`);\n }\n return chunk;\n });\n\n const bigint = parseBigInt(base6Chunks.join(\"\"), 6);\n let hex = bigint.toString(16);\n\n // ensure hex has even length\n if (hex.length % 2 !== 0) {\n hex = \"0\" + hex;\n }\n\n return Buffer.from(hex, \"hex\");\n}\n"],"x_google_ignoreList":[1],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["export * from \"./base-index\";\nexport * from \"./data\";\nexport * from \"./mnemonic\";\nexport * from \"./parse-big-int\";\n"],"mappings":""}
@@ -0,0 +1,127 @@
1
+ let node_fs_promises = require("node:fs/promises");
2
+ //#region src/base-index.ts
3
+ function oneToZeroBaseIndex(string) {
4
+ if (!/^[1-9]*$/.test(string)) throw new TypeError(`Input "${string}" contains characters other than 1-9`);
5
+ return string.replace(/\d/g, (d) => String(Number(d) - 1));
6
+ }
7
+ function zeroToOneBaseIndex(string) {
8
+ if (!/^[0-8]*$/.test(string)) throw new TypeError(`Input "${string}" contains characters other than 0-8`);
9
+ return string.replace(/\d/g, (d) => String(Number(d) + 1));
10
+ }
11
+ //#endregion
12
+ //#region src/data.ts
13
+ const numberToWordMapByType = /* @__PURE__ */ new Map();
14
+ const wordToNumberMapByType = /* @__PURE__ */ new Map();
15
+ const getEffNumberToWordMap = async (type) => {
16
+ let map = numberToWordMapByType.get(type);
17
+ if (!map) {
18
+ if (type !== "large" && type !== "short_1" && type !== "short_2_0") throw new TypeError(`Invalid type "${type}"`);
19
+ const file = await (0, node_fs_promises.readFile)(__dirname + `/../data/eff_wordlist_${type}.txt`, "utf8");
20
+ map = new Map(file.split("\n").map((it) => it.split(" ")).map(([k, v]) => [oneToZeroBaseIndex(k), v]));
21
+ numberToWordMapByType.set(type, map);
22
+ }
23
+ return map;
24
+ };
25
+ const getEffWordToNumberMap = async (type) => {
26
+ let map = wordToNumberMapByType.get(type);
27
+ if (!map) {
28
+ const numberToWordMap = await getEffNumberToWordMap(type);
29
+ map = new Map(numberToWordMap.entries().map(([k, v]) => [v, k]));
30
+ wordToNumberMapByType.set(type, map);
31
+ }
32
+ return map;
33
+ };
34
+ const clearEffCache = () => {
35
+ numberToWordMapByType.clear();
36
+ wordToNumberMapByType.clear();
37
+ };
38
+ //#endregion
39
+ //#region src/parse-big-int.ts
40
+ function parseBigInt(string, radix) {
41
+ if (radix < 2 || radix > 36) throw new TypeError("Radix must be between 2 and 36");
42
+ const bigRadix = BigInt(radix);
43
+ let result = 0n;
44
+ for (const char of string) {
45
+ const digit = parseInt(char, radix);
46
+ if (isNaN(digit)) throw new TypeError(`Invalid character "${char}" for radix ${radix}`);
47
+ result = result * bigRadix + BigInt(digit);
48
+ }
49
+ return result;
50
+ }
51
+ //#endregion
52
+ //#region src/mnemonic.ts
53
+ async function bufferToMnemonic(buffer, type = "large") {
54
+ if (!buffer.length) return [];
55
+ const numberToWordMap = await getEffNumberToWordMap(type);
56
+ const base6 = BigInt("0x" + buffer.toString("hex")).toString(6);
57
+ const rolls = type === "large" ? 5 : 4;
58
+ const base6PaddedLength = Math.ceil(base6.length / rolls) * rolls;
59
+ return (base6.padStart(base6PaddedLength, "0").match(new RegExp(`.{1,${rolls}}`, "g")) ?? []).map((chunk) => {
60
+ const word = numberToWordMap.get(chunk);
61
+ if (!word) {
62
+ const sequence = zeroToOneBaseIndex(chunk);
63
+ throw TypeError(`Sequence "${sequence}" not in ${type} list`);
64
+ }
65
+ return word;
66
+ });
67
+ }
68
+ async function mnemonicToBuffer(words, type = "large") {
69
+ if (!words.length) return Buffer.alloc(0);
70
+ const wordToBase6Map = await getEffWordToNumberMap(type);
71
+ let hex = parseBigInt(words.map((word) => {
72
+ const chunk = wordToBase6Map.get(word.toLowerCase());
73
+ if (!chunk) throw TypeError(`Word "${word}" not ${type} list`);
74
+ return chunk;
75
+ }).join(""), 6).toString(16);
76
+ if (hex.length % 2 !== 0) hex = "0" + hex;
77
+ return Buffer.from(hex, "hex");
78
+ }
79
+ //#endregion
80
+ Object.defineProperty(exports, "bufferToMnemonic", {
81
+ enumerable: true,
82
+ get: function() {
83
+ return bufferToMnemonic;
84
+ }
85
+ });
86
+ Object.defineProperty(exports, "clearEffCache", {
87
+ enumerable: true,
88
+ get: function() {
89
+ return clearEffCache;
90
+ }
91
+ });
92
+ Object.defineProperty(exports, "getEffNumberToWordMap", {
93
+ enumerable: true,
94
+ get: function() {
95
+ return getEffNumberToWordMap;
96
+ }
97
+ });
98
+ Object.defineProperty(exports, "getEffWordToNumberMap", {
99
+ enumerable: true,
100
+ get: function() {
101
+ return getEffWordToNumberMap;
102
+ }
103
+ });
104
+ Object.defineProperty(exports, "mnemonicToBuffer", {
105
+ enumerable: true,
106
+ get: function() {
107
+ return mnemonicToBuffer;
108
+ }
109
+ });
110
+ Object.defineProperty(exports, "oneToZeroBaseIndex", {
111
+ enumerable: true,
112
+ get: function() {
113
+ return oneToZeroBaseIndex;
114
+ }
115
+ });
116
+ Object.defineProperty(exports, "parseBigInt", {
117
+ enumerable: true,
118
+ get: function() {
119
+ return parseBigInt;
120
+ }
121
+ });
122
+ Object.defineProperty(exports, "zeroToOneBaseIndex", {
123
+ enumerable: true,
124
+ get: function() {
125
+ return zeroToOneBaseIndex;
126
+ }
127
+ });
@@ -0,0 +1,115 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { readFile } from "node:fs/promises";
4
+ //#region \0rolldown/runtime.js
5
+ var __esmMin = (fn, res, err) => () => {
6
+ if (err) throw err[0];
7
+ try {
8
+ return fn && (res = fn(fn = 0)), res;
9
+ } catch (e) {
10
+ throw err = [e], e;
11
+ }
12
+ };
13
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
14
+ //#endregion
15
+ //#region src/base-index.ts
16
+ function oneToZeroBaseIndex(string) {
17
+ if (!/^[1-9]*$/.test(string)) throw new TypeError(`Input "${string}" contains characters other than 1-9`);
18
+ return string.replace(/\d/g, (d) => String(Number(d) - 1));
19
+ }
20
+ function zeroToOneBaseIndex(string) {
21
+ if (!/^[0-8]*$/.test(string)) throw new TypeError(`Input "${string}" contains characters other than 0-8`);
22
+ return string.replace(/\d/g, (d) => String(Number(d) + 1));
23
+ }
24
+ var init_base_index = __esmMin((() => {}));
25
+ //#endregion
26
+ //#region node_modules/tsdown/esm-shims.js
27
+ var getFilename, getDirname, __dirname;
28
+ var init_esm_shims = __esmMin((() => {
29
+ getFilename = () => fileURLToPath(import.meta.url);
30
+ getDirname = () => path.dirname(getFilename());
31
+ __dirname = /* @__PURE__ */ getDirname();
32
+ }));
33
+ //#endregion
34
+ //#region src/data.ts
35
+ var numberToWordMapByType, wordToNumberMapByType, getEffNumberToWordMap, getEffWordToNumberMap, clearEffCache;
36
+ var init_data = __esmMin((() => {
37
+ init_esm_shims();
38
+ init_base_index();
39
+ numberToWordMapByType = /* @__PURE__ */ new Map();
40
+ wordToNumberMapByType = /* @__PURE__ */ new Map();
41
+ getEffNumberToWordMap = async (type) => {
42
+ let map = numberToWordMapByType.get(type);
43
+ if (!map) {
44
+ if (type !== "large" && type !== "short_1" && type !== "short_2_0") throw new TypeError(`Invalid type "${type}"`);
45
+ const file = await readFile(__dirname + `/../data/eff_wordlist_${type}.txt`, "utf8");
46
+ map = new Map(file.split("\n").map((it) => it.split(" ")).map(([k, v]) => [oneToZeroBaseIndex(k), v]));
47
+ numberToWordMapByType.set(type, map);
48
+ }
49
+ return map;
50
+ };
51
+ getEffWordToNumberMap = async (type) => {
52
+ let map = wordToNumberMapByType.get(type);
53
+ if (!map) {
54
+ const numberToWordMap = await getEffNumberToWordMap(type);
55
+ map = new Map(numberToWordMap.entries().map(([k, v]) => [v, k]));
56
+ wordToNumberMapByType.set(type, map);
57
+ }
58
+ return map;
59
+ };
60
+ clearEffCache = () => {
61
+ numberToWordMapByType.clear();
62
+ wordToNumberMapByType.clear();
63
+ };
64
+ }));
65
+ //#endregion
66
+ //#region src/parse-big-int.ts
67
+ function parseBigInt(string, radix) {
68
+ if (radix < 2 || radix > 36) throw new TypeError("Radix must be between 2 and 36");
69
+ const bigRadix = BigInt(radix);
70
+ let result = 0n;
71
+ for (const char of string) {
72
+ const digit = parseInt(char, radix);
73
+ if (isNaN(digit)) throw new TypeError(`Invalid character "${char}" for radix ${radix}`);
74
+ result = result * bigRadix + BigInt(digit);
75
+ }
76
+ return result;
77
+ }
78
+ var init_parse_big_int = __esmMin((() => {}));
79
+ //#endregion
80
+ //#region src/mnemonic.ts
81
+ async function bufferToMnemonic(buffer, type = "large") {
82
+ if (!buffer.length) return [];
83
+ const numberToWordMap = await getEffNumberToWordMap(type);
84
+ const base6 = BigInt("0x" + buffer.toString("hex")).toString(6);
85
+ const rolls = type === "large" ? 5 : 4;
86
+ const base6PaddedLength = Math.ceil(base6.length / rolls) * rolls;
87
+ return (base6.padStart(base6PaddedLength, "0").match(new RegExp(`.{1,${rolls}}`, "g")) ?? []).map((chunk) => {
88
+ const word = numberToWordMap.get(chunk);
89
+ if (!word) {
90
+ const sequence = zeroToOneBaseIndex(chunk);
91
+ throw TypeError(`Sequence "${sequence}" not in ${type} list`);
92
+ }
93
+ return word;
94
+ });
95
+ }
96
+ async function mnemonicToBuffer(words, type = "large") {
97
+ if (!words.length) return Buffer.alloc(0);
98
+ const wordToBase6Map = await getEffWordToNumberMap(type);
99
+ let hex = parseBigInt(words.map((word) => {
100
+ const chunk = wordToBase6Map.get(word.toLowerCase());
101
+ if (!chunk) throw TypeError(`Word "${word}" not ${type} list`);
102
+ return chunk;
103
+ }).join(""), 6).toString(16);
104
+ if (hex.length % 2 !== 0) hex = "0" + hex;
105
+ return Buffer.from(hex, "hex");
106
+ }
107
+ var init_mnemonic = __esmMin((() => {
108
+ init_base_index();
109
+ init_data();
110
+ init_parse_big_int();
111
+ }));
112
+ //#endregion
113
+ export { parseBigInt as a, getEffWordToNumberMap as c, oneToZeroBaseIndex as d, zeroToOneBaseIndex as f, init_parse_big_int as i, init_data as l, init_mnemonic as n, clearEffCache as o, __commonJSMin as p, mnemonicToBuffer as r, getEffNumberToWordMap as s, bufferToMnemonic as t, init_base_index as u };
114
+
115
+ //# sourceMappingURL=mnemonic-JeCBHZim.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mnemonic-JeCBHZim.mjs","names":[],"sources":["../src/base-index.ts","../node_modules/tsdown/esm-shims.js","../src/data.ts","../src/parse-big-int.ts","../src/mnemonic.ts"],"sourcesContent":["export function oneToZeroBaseIndex(string: string) {\n if (!/^[1-9]*$/.test(string)) {\n throw new TypeError(`Input \"${string}\" contains characters other than 1-9`);\n }\n\n return string.replace(/\\d/g, (d) => String(Number(d) - 1));\n}\n\nexport function zeroToOneBaseIndex(string: string) {\n if (!/^[0-8]*$/.test(string)) {\n throw new TypeError(`Input \"${string}\" contains characters other than 0-8`);\n }\n\n return string.replace(/\\d/g, (d) => String(Number(d) + 1));\n}\n","// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import { readFile } from \"node:fs/promises\";\nimport { oneToZeroBaseIndex } from \"./base-index\";\n\nconst numberToWordMapByType = new Map<EffWordListType, EffWordMap>();\nconst wordToNumberMapByType = new Map<EffWordListType, EffWordMap>();\n\nexport type EffWordListType = \"large\" | \"short_1\" | \"short_2_0\";\nexport type EffWordMap = Map<string, string>;\n\nexport const getEffNumberToWordMap = async (type: EffWordListType) => {\n let map = numberToWordMapByType.get(type);\n\n // load map from file if already not loaded\n if (!map) {\n if (type !== \"large\" && type !== \"short_1\" && type !== \"short_2_0\") {\n throw new TypeError(`Invalid type \"${type}\"`);\n }\n\n const file = await readFile(\n __dirname + `/../data/eff_wordlist_${type}.txt`,\n \"utf8\",\n );\n\n // parse wordlist and build a map\n // NOTE: the dice rolls use numbers from 1 to 6, we convert this to a\n // zero based index or a base6 number\n map = new Map(\n file\n .split(\"\\n\")\n .map((it) => it.split(\"\\t\") as [string, string])\n .map(([k, v]) => [oneToZeroBaseIndex(k), v]),\n );\n\n // cache map\n numberToWordMapByType.set(type, map);\n }\n\n return map;\n};\n\nexport const getEffWordToNumberMap = async (type: EffWordListType) => {\n let map = wordToNumberMapByType.get(type);\n\n // load map from file if already not loaded\n if (!map) {\n const numberToWordMap = await getEffNumberToWordMap(type);\n\n // invert number to word map\n map = new Map(numberToWordMap.entries().map(([k, v]) => [v, k]));\n\n // cache map\n wordToNumberMapByType.set(type, map);\n }\n\n return map;\n};\n\nexport const clearEffCache = () => {\n numberToWordMapByType.clear();\n wordToNumberMapByType.clear();\n};\n","export function parseBigInt(string: string, radix: number) {\n if (radix < 2 || radix > 36) {\n throw new TypeError(\"Radix must be between 2 and 36\");\n }\n\n const bigRadix = BigInt(radix);\n\n let result = 0n;\n for (const char of string) {\n const digit = parseInt(char, radix);\n\n if (isNaN(digit)) {\n throw new TypeError(`Invalid character \"${char}\" for radix ${radix}`);\n }\n\n result = result * bigRadix + BigInt(digit);\n }\n\n return result;\n}\n","import { zeroToOneBaseIndex } from \"./base-index\";\nimport {\n EffWordListType,\n getEffNumberToWordMap,\n getEffWordToNumberMap,\n} from \"./data\";\nimport { parseBigInt } from \"./parse-big-int\";\n\nexport async function bufferToMnemonic(\n buffer: Buffer,\n type: EffWordListType = \"large\",\n) {\n // handle empty input\n if (!buffer.length) {\n return [];\n }\n\n const numberToWordMap = await getEffNumberToWordMap(type);\n const bigint = BigInt(\"0x\" + buffer.toString(\"hex\"));\n const base6 = bigint.toString(6);\n\n // pad string to ensure length is a multiple of number of dice rolls\n const rolls = type === \"large\" ? 5 : 4;\n const base6PaddedLength = Math.ceil(base6.length / rolls) * rolls;\n const base6Padded = base6.padStart(base6PaddedLength, \"0\");\n\n // split base6 string into chunks and map to words\n const base6Chunks = base6Padded.match(new RegExp(`.{1,${rolls}}`, \"g\")) ?? [];\n return base6Chunks.map((chunk) => {\n const word = numberToWordMap.get(chunk);\n if (!word) {\n const sequence = zeroToOneBaseIndex(chunk);\n throw TypeError(`Sequence \"${sequence}\" not in ${type} list`);\n }\n return word;\n });\n}\n\nexport async function mnemonicToBuffer(\n words: string[],\n type: EffWordListType = \"large\",\n) {\n // handle empty input\n if (!words.length) {\n return Buffer.alloc(0);\n }\n\n const wordToBase6Map = await getEffWordToNumberMap(type);\n const base6Chunks = words.map((word) => {\n const chunk = wordToBase6Map.get(word.toLowerCase());\n if (!chunk) {\n throw TypeError(`Word \"${word}\" not ${type} list`);\n }\n return chunk;\n });\n\n const bigint = parseBigInt(base6Chunks.join(\"\"), 6);\n let hex = bigint.toString(16);\n\n // ensure hex has even length\n if (hex.length % 2 !== 0) {\n hex = \"0\" + hex;\n }\n\n return Buffer.from(hex, \"hex\");\n}\n"],"x_google_ignoreList":[1],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eff-mnemonic",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Convert buffers to and from a human-readable mnemonic phrase using the eff wordlists",
5
5
  "keywords": [
6
6
  "eff",
@@ -37,14 +37,19 @@
37
37
  "require": "./dist/index.js"
38
38
  }
39
39
  },
40
+ "bin": {
41
+ "eff-mnemonic": "./bin/eff-mnemonic"
42
+ },
40
43
  "files": [
44
+ "bin",
41
45
  "data",
42
46
  "dist"
43
47
  ],
44
48
  "scripts": {
45
49
  "test": "node --import tsx --test src/**/*.test.ts",
46
- "build": "tsdown --shims --format cjs,esm --clean --dts src/index.ts",
47
- "prepublishOnly": "npm run test && npm run build"
50
+ "build": "tsdown --shims --format cjs,esm --clean --dts src/index.ts src/cli.ts",
51
+ "prepare": "npm run build",
52
+ "prepublishOnly": "npm run build && npm run test"
48
53
  },
49
54
  "devDependencies": {
50
55
  "@types/node": "^26.1.1",