nano-pow 3.1.1 → 3.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/cli.js +65 -23
- package/dist/main.min.js +62 -32
- package/dist/nano-pow.1 +24 -18
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -143,7 +143,8 @@ Email: <bug-nano-pow@zoso.dev>
|
|
|
143
143
|
implementation
|
|
144
144
|
|
|
145
145
|
## Licenses
|
|
146
|
-
|
|
146
|
+
GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
|
|
147
|
+
Portions of this code are also provided under the MIT License: <https://spdx.org/licenses/MIT.html>
|
|
147
148
|
|
|
148
149
|
## Donations
|
|
149
150
|
If you find this package helpful, please consider tipping the developer.
|
package/dist/cli.js
CHANGED
|
@@ -2,28 +2,43 @@
|
|
|
2
2
|
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
|
|
3
3
|
//! SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
import * as puppeteer from 'puppeteer'
|
|
6
5
|
import * as fs from 'node:fs/promises'
|
|
6
|
+
import * as readline from 'node:readline/promises'
|
|
7
|
+
import * as puppeteer from 'puppeteer'
|
|
8
|
+
|
|
9
|
+
const hashes = []
|
|
10
|
+
|
|
11
|
+
const stdinErrors = []
|
|
12
|
+
if (!process.stdin.isTTY) {
|
|
13
|
+
const stdin = readline.createInterface({
|
|
14
|
+
input: process.stdin
|
|
15
|
+
})
|
|
16
|
+
for await (const line of stdin) {
|
|
17
|
+
if (/^[0-9A-Fa-f]{64}$/.test(line)) {
|
|
18
|
+
hashes.push(line)
|
|
19
|
+
} else {
|
|
20
|
+
stdinErrors.push(`Skipping invalid stdin input: ${line}`)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
7
24
|
|
|
8
25
|
const args = process.argv.slice(2)
|
|
9
|
-
if (args.length === 0 || args.some(v => v === '--help' || v === '-h')) {
|
|
26
|
+
if ((hashes.length === 0 && args.length === 0) || (args.some(v => v === '--help' || v === '-h'))) {
|
|
10
27
|
console.log(`Usage: nano-pow [OPTION]... BLOCKHASH...
|
|
11
28
|
Generate work for BLOCKHASH, or multiple work values for BLOCKHASH(es)
|
|
12
|
-
BLOCKHASH is a 64-character hexadecimal string.
|
|
13
|
-
|
|
14
|
-
Prints a 16-character hexadecimal work value to standard output.
|
|
15
|
-
If using --validate, prints 'true' or 'false' to standard output instead.
|
|
16
|
-
All command options are optional.
|
|
29
|
+
BLOCKHASH is a 64-character hexadecimal string. Multiple blockhashes must be separated by whitespace or line breaks.
|
|
30
|
+
Prints a 16-character hexadecimal work value to standard output. If using --validate, prints 'true' or 'false' to standard output instead.
|
|
17
31
|
|
|
18
32
|
-h, --help show this dialog
|
|
19
33
|
-d, --debug enable additional logging output
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
34
|
+
-j, --json format output as JSON
|
|
35
|
+
-e, --effort=<value> increase demand on GPU processing
|
|
36
|
+
-t, --threshold=<value> override the minimum threshold value
|
|
37
|
+
-v, --validate=<value> check an existing work value instead of searching for one
|
|
23
38
|
|
|
24
39
|
If validating a nonce, it must be a 16-character hexadecimal value.
|
|
25
|
-
Effort must be a decimal number between 1
|
|
26
|
-
Threshold must be a hexadecimal
|
|
40
|
+
Effort must be a decimal number between 1-32.
|
|
41
|
+
Threshold must be a hexadecimal string between 0-FFFFFFFF.
|
|
27
42
|
|
|
28
43
|
Report bugs: <bug-nano-pow@zoso.dev>
|
|
29
44
|
Full documentation: <https://www.npmjs.com/package/nano-pow>
|
|
@@ -31,18 +46,17 @@ Full documentation: <https://www.npmjs.com/package/nano-pow>
|
|
|
31
46
|
process.exit()
|
|
32
47
|
}
|
|
33
48
|
|
|
34
|
-
const
|
|
49
|
+
const inArgs = []
|
|
35
50
|
while (/^[0-9A-Fa-f]{64}$/.test(args[args.length - 1] ?? '')) {
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
if (hashes.length === 0) {
|
|
39
|
-
console.error('Invalid block hash input')
|
|
40
|
-
process.exit(1)
|
|
51
|
+
inArgs.unshift(args.pop())
|
|
41
52
|
}
|
|
53
|
+
hashes.push(...inArgs)
|
|
42
54
|
|
|
43
55
|
let fn = 'search'
|
|
44
56
|
let work = ''
|
|
57
|
+
let isJson = false
|
|
45
58
|
const options = {}
|
|
59
|
+
|
|
46
60
|
for (let i = 0; i < args.length; i++) {
|
|
47
61
|
switch (args[i]) {
|
|
48
62
|
case ('--validate'):
|
|
@@ -72,13 +86,27 @@ for (let i = 0; i < args.length; i++) {
|
|
|
72
86
|
options['debug'] = true
|
|
73
87
|
break
|
|
74
88
|
}
|
|
89
|
+
case ('--json'):
|
|
90
|
+
case ('-j'): {
|
|
91
|
+
isJson = true
|
|
92
|
+
break
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (options['debug']) {
|
|
98
|
+
console.log(`NanoPowCli.${fn}()`)
|
|
99
|
+
console.log(`${fn} options`, JSON.stringify(options))
|
|
100
|
+
for (const stdinErr of stdinErrors) {
|
|
101
|
+
console.warn(stdinErr)
|
|
75
102
|
}
|
|
76
103
|
}
|
|
77
104
|
|
|
78
|
-
if (
|
|
79
|
-
|
|
105
|
+
if (hashes.length === 0) {
|
|
106
|
+
console.error('Invalid block hash input')
|
|
107
|
+
process.exit(1)
|
|
108
|
+
}
|
|
80
109
|
|
|
81
|
-
;
|
|
82
110
|
/**
|
|
83
111
|
* Main
|
|
84
112
|
*/
|
|
@@ -105,10 +133,22 @@ if (options['debug']) console.log(`${fn} options`, JSON.stringify(options))
|
|
|
105
133
|
const output = msg.text().split(' ')
|
|
106
134
|
if (output[0] === 'cli') {
|
|
107
135
|
if (output[1] === 'exit') {
|
|
136
|
+
if (isJson) {
|
|
137
|
+
const results = await page.evaluate(() => {
|
|
138
|
+
return window.results
|
|
139
|
+
})
|
|
140
|
+
for (let i = 0; i < results.length; i++) {
|
|
141
|
+
results[i] = {
|
|
142
|
+
blockhash: hashes[i],
|
|
143
|
+
work: results[i]
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
console.log(JSON.stringify(results, null, 4))
|
|
147
|
+
}
|
|
108
148
|
const end = performance.now()
|
|
109
149
|
if (options['debug']) console.log(end - start, 'ms total |', (end - start) / hashes.length, 'ms avg')
|
|
110
|
-
|
|
111
|
-
} else {
|
|
150
|
+
await browser.close()
|
|
151
|
+
} else if (!isJson) {
|
|
112
152
|
console.log(output[1])
|
|
113
153
|
}
|
|
114
154
|
} else if (options['debug']) {
|
|
@@ -128,10 +168,12 @@ if (options['debug']) console.log(`${fn} options`, JSON.stringify(options))
|
|
|
128
168
|
createScript: string => string,
|
|
129
169
|
})
|
|
130
170
|
${NanoPow}
|
|
171
|
+
window.results = []
|
|
131
172
|
const hashes = ["${hashes.join('","')}"]
|
|
132
173
|
for (const hash of hashes) {
|
|
133
174
|
try {
|
|
134
175
|
const work = await NanoPow.${fn}(${work}hash, ${JSON.stringify(options)})
|
|
176
|
+
window.results.push(work)
|
|
135
177
|
console.log(\`cli \${work}\`)
|
|
136
178
|
} catch (err) {
|
|
137
179
|
console.error(\`cli \${err}\`)
|
package/dist/main.min.js
CHANGED
|
@@ -68,6 +68,66 @@ layout(std140) uniform WORK {
|
|
|
68
68
|
uvec2 seed;
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Initialization vector defined by BLAKE2. Each vec2<u32> represents two halves
|
|
73
|
+
* of the original u64 value from the reference implementation. They appear
|
|
74
|
+
* reversed pairwise as defined below, but this is an illusion due to endianness:
|
|
75
|
+
* the \`x\` component of the vector is the low bits and the \`y\` component is the
|
|
76
|
+
* high bits, and if you laid the bits out individually, they would match the
|
|
77
|
+
* little-endian 64-bit representation.
|
|
78
|
+
*/
|
|
79
|
+
const uvec2 BLAKE2B_IV[8] = uvec2[8](
|
|
80
|
+
uvec2(0xF3BCC908u, 0x6A09E667u),
|
|
81
|
+
uvec2(0x84CAA73Bu, 0xBB67AE85u),
|
|
82
|
+
uvec2(0xFE94F82Bu, 0x3C6EF372u),
|
|
83
|
+
uvec2(0x5F1D36F1u, 0xA54FF53Au),
|
|
84
|
+
uvec2(0xADE682D1u, 0x510E527Fu),
|
|
85
|
+
uvec2(0x2B3E6C1Fu, 0x9B05688Cu),
|
|
86
|
+
uvec2(0xFB41BD6Bu, 0x1F83D9ABu),
|
|
87
|
+
uvec2(0x137E2179u, 0x5BE0CD19u)
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Parameter block as defined in BLAKE2 section 2.8 and configured as follows:
|
|
92
|
+
* maximal depth = 1, fanout = 1, digest byte length = 8
|
|
93
|
+
*/
|
|
94
|
+
const uvec2 BLAKE2B_PARAM = uvec2(0x01010008u, 0u);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Message input length which is always 40 for Nano.
|
|
98
|
+
* 8 nonce bytes + 32 block hash bytes
|
|
99
|
+
*/
|
|
100
|
+
const uvec2 BLAKE2B_INLEN = uvec2(0x00000028u, 0u);
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Finalization flag as defined in BLAKE2 section 2.4 and set to ~0 since this is
|
|
104
|
+
* the final (and only) message block being hashed.
|
|
105
|
+
*/
|
|
106
|
+
const uvec2 BLAKE2B_FINAL = uvec2(0xFFFFFFFFu, 0xFFFFFFFFu);
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Fully initialized state array that is locally copied at each thread start.
|
|
110
|
+
* Application of each XOR is defined by BLAKE2 section 2.4 compression function.
|
|
111
|
+
*/
|
|
112
|
+
const uvec2 BLAKE2B_INIT[16] = uvec2[16](
|
|
113
|
+
BLAKE2B_IV[0u] ^ BLAKE2B_PARAM,
|
|
114
|
+
BLAKE2B_IV[1u],
|
|
115
|
+
BLAKE2B_IV[2u],
|
|
116
|
+
BLAKE2B_IV[3u],
|
|
117
|
+
BLAKE2B_IV[4u],
|
|
118
|
+
BLAKE2B_IV[5u],
|
|
119
|
+
BLAKE2B_IV[6u],
|
|
120
|
+
BLAKE2B_IV[7u],
|
|
121
|
+
BLAKE2B_IV[0u],
|
|
122
|
+
BLAKE2B_IV[1u],
|
|
123
|
+
BLAKE2B_IV[2u],
|
|
124
|
+
BLAKE2B_IV[3u],
|
|
125
|
+
BLAKE2B_IV[4u] ^ BLAKE2B_INLEN,
|
|
126
|
+
BLAKE2B_IV[5u],
|
|
127
|
+
BLAKE2B_IV[6u] ^ BLAKE2B_FINAL,
|
|
128
|
+
BLAKE2B_IV[7u]
|
|
129
|
+
);
|
|
130
|
+
|
|
71
131
|
// Defined separately from uint v[0].y below as the original value is required
|
|
72
132
|
// to calculate the second uint32 of the digest for threshold comparison
|
|
73
133
|
const uint BLAKE2B_IV32_1 = 0x6A09E667u;
|
|
@@ -79,36 +139,6 @@ const uvec4 ROTATE_16 = uvec4(16u);
|
|
|
79
139
|
const uvec4 ROTATE_24 = uvec4(24u);
|
|
80
140
|
const uvec4 ROTATE_31 = uvec4(31u);
|
|
81
141
|
|
|
82
|
-
// Both buffers represent 16 uint64s as 32 uint32s
|
|
83
|
-
// because that's what GLSL offers, just like Javascript
|
|
84
|
-
|
|
85
|
-
// Compression buffer, intialized to 2 instances of the initialization vector
|
|
86
|
-
// The following values have been modified from the BLAKE2B_IV:
|
|
87
|
-
// OUTLEN is constant 8 bytes
|
|
88
|
-
// v[0] ^= 0x01010000u ^ uint(OUTLEN);
|
|
89
|
-
// INLEN is constant 40 bytes: work value (8) + block hash (32)
|
|
90
|
-
// v[12] ^= uint(INLEN);
|
|
91
|
-
// It's always the "last" compression at this INLEN
|
|
92
|
-
// v[14] = ~v[14];
|
|
93
|
-
const uvec2 blake2b_iv[16] = uvec2[16](
|
|
94
|
-
uvec2(0xF2BDC900u, 0x6A09E667u),
|
|
95
|
-
uvec2(0x84CAA73Bu, 0xBB67AE85u),
|
|
96
|
-
uvec2(0xFE94F82Bu, 0x3C6EF372u),
|
|
97
|
-
uvec2(0x5F1D36F1u, 0xA54FF53Au),
|
|
98
|
-
uvec2(0xADE682D1u, 0x510E527Fu),
|
|
99
|
-
uvec2(0x2B3E6C1Fu, 0x9B05688Cu),
|
|
100
|
-
uvec2(0xFB41BD6Bu, 0x1F83D9ABu),
|
|
101
|
-
uvec2(0x137E2179u, 0x5BE0CD19u),
|
|
102
|
-
uvec2(0xF3BCC908u, 0x6A09E667u),
|
|
103
|
-
uvec2(0x84CAA73Bu, 0xBB67AE85u),
|
|
104
|
-
uvec2(0xFE94F82Bu, 0x3C6EF372u),
|
|
105
|
-
uvec2(0x5F1D36F1u, 0xA54FF53Au),
|
|
106
|
-
uvec2(0xADE682F9u, 0x510E527Fu),
|
|
107
|
-
uvec2(0x2B3E6C1Fu, 0x9B05688Cu),
|
|
108
|
-
uvec2(0x04BE4294u, 0xE07C2654u),
|
|
109
|
-
uvec2(0x137E2179u, 0x5BE0CD19u)
|
|
110
|
-
);
|
|
111
|
-
|
|
112
142
|
// Iterated initialization vector
|
|
113
143
|
uvec2 v[16];
|
|
114
144
|
|
|
@@ -162,7 +192,7 @@ void main() {
|
|
|
162
192
|
m[4u] = uvec2(blockhash[6u], blockhash[7u]);
|
|
163
193
|
|
|
164
194
|
// Reset v
|
|
165
|
-
v =
|
|
195
|
+
v = BLAKE2B_INIT;
|
|
166
196
|
|
|
167
197
|
// Twelve rounds of G mixing
|
|
168
198
|
|
|
@@ -240,7 +270,7 @@ void main() {
|
|
|
240
270
|
|
|
241
271
|
// Pixel data set from work seed values
|
|
242
272
|
// Finalize digest from high bits, low bits can be safely ignored
|
|
243
|
-
if ((
|
|
273
|
+
if ((BLAKE2B_INIT[0u].y ^ v[0u].y ^ v[8u].y) >= threshold && (search || uvec2(gl_FragCoord) == uvec2(0u))) {
|
|
244
274
|
nonce = uvec4(1u, m[0u].y, m[0u].x, (uint(gl_FragCoord.x) << 16u) | uint(gl_FragCoord.y));
|
|
245
275
|
}
|
|
246
276
|
|
package/dist/nano-pow.1
CHANGED
|
@@ -11,15 +11,10 @@ nano-pow \- proof-of-work generation and validation for Nano cryptocurrency
|
|
|
11
11
|
|
|
12
12
|
.SH DESCRIPTION
|
|
13
13
|
Generate work for \fIBLOCKHASH\fR, or multiple work values for \fIBLOCKHASH\fR(es).
|
|
14
|
-
Nano PoW documentation: <https://docs.nano.org/integration-guides/work-generation/\#work-calculation-details>
|
|
15
14
|
.PP
|
|
16
|
-
\fIBLOCKHASH\fR is a 64-character hexadecimal string.
|
|
15
|
+
\fIBLOCKHASH\fR is a 64-character hexadecimal string. Multiple blockhashes must be separated by whitespace or line breaks.
|
|
17
16
|
.PP
|
|
18
|
-
|
|
19
|
-
.PP
|
|
20
|
-
Prints a 16-character hexadecimal work value to standard output.
|
|
21
|
-
.PP
|
|
22
|
-
If \fB--validate\fR is used, prints 'true' or 'false' to standard output.
|
|
17
|
+
Prints a 16-character hexadecimal work value to standard output. If \fB--validate\fR is used, prints 'true' or 'false' to standard output.
|
|
23
18
|
|
|
24
19
|
.SH OPTIONS
|
|
25
20
|
.TP
|
|
@@ -29,43 +24,54 @@ Show this help dialog and exit.
|
|
|
29
24
|
\fB\-d\fR, \fB\-\-debug\fR
|
|
30
25
|
Enable additional logging output.
|
|
31
26
|
.TP
|
|
32
|
-
\fB\-
|
|
27
|
+
\fB\-j\fR, \fB\-\-json\fR
|
|
28
|
+
Format output as JSON.
|
|
29
|
+
.TP
|
|
30
|
+
\fB\-e\fR, \fB\-\-effort\fR=\fIEFFORT\fR
|
|
33
31
|
Increase demand on GPU processing. Must be between 1 and 32 inclusive.
|
|
34
32
|
.TP
|
|
35
|
-
\fB\-t\fR, \fB\-\-threshold\fR
|
|
36
|
-
Override the minimum threshold value. Higher values increase difficulty. Must be
|
|
33
|
+
\fB\-t\fR, \fB\-\-threshold\fR=\fITHRESHOLD\fR
|
|
34
|
+
Override the minimum threshold value. Higher values increase difficulty. Must be a hexadecimal string between 0 and FFFFFFFF inclusive.
|
|
37
35
|
.TP
|
|
38
|
-
\fB\-v\fR, \fB\-\-validate\fR
|
|
36
|
+
\fB\-v\fR, \fB\-\-validate\fR=\fIWORK\fR
|
|
39
37
|
Check an existing work value instead of searching for one.
|
|
40
38
|
|
|
41
39
|
.SH EXAMPLES
|
|
40
|
+
.PP
|
|
42
41
|
Search for a work nonce for a blockhash using the default threshold 0xFFFFFFF8:
|
|
43
42
|
.EX
|
|
44
|
-
nano-pow
|
|
43
|
+
$ nano-pow \fB0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\fR
|
|
45
44
|
.EE
|
|
46
45
|
|
|
46
|
+
.PP
|
|
47
47
|
Search for a work nonce using a custom threshold and increased effort:
|
|
48
48
|
.EX
|
|
49
|
-
nano-pow \-t fffffe00 \-e 32 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
|
49
|
+
$ nano-pow \fB\-t fffffe00 \-e 32 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\fR
|
|
50
50
|
.EE
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
.PP
|
|
53
|
+
Read one or more lines of blockhashes from a file and output to another file:
|
|
53
54
|
.EX
|
|
54
|
-
|
|
55
|
+
$ cat /path/to/file.txt | nano-pow --json > work.json
|
|
55
56
|
.EE
|
|
56
57
|
|
|
58
|
+
.PP
|
|
57
59
|
Validate an existing work nonce against a blockhash and show debugging output:
|
|
58
60
|
.EX
|
|
59
|
-
nano-pow \-d \-v fedcba9876543210 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
|
61
|
+
$ nano-pow \fB\-d \-v fedcba9876543210 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\fR
|
|
60
62
|
.EE
|
|
61
63
|
|
|
62
64
|
.SH AUTHOR
|
|
63
65
|
Written by Chris Duncan.
|
|
64
66
|
|
|
65
67
|
.SH BUGS
|
|
66
|
-
Email
|
|
68
|
+
Email <bug-nano-pow@zoso.dev>.
|
|
67
69
|
|
|
68
70
|
.SH COPYRIGHT
|
|
69
|
-
Copyright \(co 2025 Chris Duncan <chris@zoso.dev>
|
|
70
71
|
.PP
|
|
72
|
+
.EX
|
|
73
|
+
Copyright \(co 2025 Chris Duncan <chris@zoso.dev>
|
|
74
|
+
Nano PoW documentation: <https://docs.nano.org/integration-guides/work-generation/#work-calculation-details>
|
|
71
75
|
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
|
|
76
|
+
Portions of this code are also provided under the MIT License: <https://spdx.org/licenses/MIT.html>
|
|
77
|
+
.EE
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nano-pow",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3",
|
|
4
4
|
"description": "Proof-of-work generation and validation with WebGPU/WebGL for Nano cryptocurrency.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nemo",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"cash",
|
|
9
9
|
"crypto",
|
|
10
10
|
"currency",
|
|
11
|
+
"cryptocurrency",
|
|
11
12
|
"coin",
|
|
12
13
|
"nonce",
|
|
13
14
|
"pow",
|
|
@@ -32,8 +33,7 @@
|
|
|
32
33
|
],
|
|
33
34
|
"main": "dist/main.min.js",
|
|
34
35
|
"browser": {
|
|
35
|
-
"dist/main.min.js": true
|
|
36
|
-
"node:worker_threads": false
|
|
36
|
+
"./dist/main.min.js": true
|
|
37
37
|
},
|
|
38
38
|
"bin": "./dist/cli.js",
|
|
39
39
|
"man": "./dist/nano-pow.1",
|
|
@@ -53,10 +53,12 @@
|
|
|
53
53
|
"typescript": "^5.8.2"
|
|
54
54
|
},
|
|
55
55
|
"type": "module",
|
|
56
|
-
"exports":
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
"exports": {
|
|
57
|
+
".": {
|
|
58
|
+
"types": "./dist/types.d.ts",
|
|
59
|
+
"default": "./dist/main.min.js"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
60
62
|
"types": "./dist/types.d.ts",
|
|
61
63
|
"unpkg": "./dist/main.min.js",
|
|
62
64
|
"optionalDependencies": {
|