@witnet/sdk 1.2.1 → 1.2.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/.env_witnet +2 -1
- package/dist/package.json +5 -3
- package/dist/src/bin/helpers.js +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/lib/crypto/account.js +1 -1
- package/dist/src/lib/crypto/coinbase.js +1 -1
- package/dist/src/lib/crypto/index.js +1 -1
- package/dist/src/lib/crypto/interfaces.js +1 -1
- package/dist/src/lib/crypto/payloads/DataRequestPayload.js +1 -1
- package/dist/src/lib/crypto/payloads/StakePayload.js +1 -1
- package/dist/src/lib/crypto/payloads/UnstakePayload.js +1 -1
- package/dist/src/lib/crypto/payloads/ValueTransferPayload.js +1 -1
- package/dist/src/lib/crypto/payloads.js +1 -1
- package/dist/src/lib/crypto/signer.js +1 -1
- package/dist/src/lib/crypto/transmitters/DataRequests.js +1 -1
- package/dist/src/lib/crypto/transmitters/StakeDeposits.js +1 -1
- package/dist/src/lib/crypto/transmitters/StakeWithdrawals.js +1 -1
- package/dist/src/lib/crypto/transmitters/ValueTransfers.js +1 -1
- package/dist/src/lib/crypto/transmitters.js +1 -1
- package/dist/src/lib/crypto/types.js +1 -1
- package/dist/src/lib/crypto/utils.js +1 -1
- package/dist/src/lib/crypto/wallet.js +1 -1
- package/dist/src/lib/index.js +1 -1
- package/dist/src/lib/radon/ccdr/eth.js +1 -1
- package/dist/src/lib/radon/ccdr/index.js +1 -1
- package/dist/src/lib/radon/ccdr/wit.js +1 -1
- package/dist/src/lib/radon/filters.js +1 -1
- package/dist/src/lib/radon/index.js +1 -1
- package/dist/src/lib/radon/reducers.js +1 -1
- package/dist/src/lib/radon/types.js +1 -1
- package/dist/src/lib/radon/utils.d.ts.map +1 -1
- package/dist/src/lib/radon/utils.js +1 -1
- package/dist/src/lib/rest/kermit.d.ts.map +1 -1
- package/dist/src/lib/rest/kermit.js +2 -4
- package/dist/src/lib/rest/types.js +1 -1
- package/dist/src/lib/rpc/index.js +1 -1
- package/dist/src/lib/rpc/nodes.js +1 -1
- package/dist/src/lib/rpc/provider.js +1 -1
- package/dist/src/lib/rpc/types.js +1 -1
- package/dist/src/lib/types.js +1 -1
- package/dist/src/lib/utils.js +1 -1
- package/package.json +5 -3
- package/scripts/clean.cjs +21 -0
- package/scripts/postinstall.cjs +9 -0
- package/src/bin/bots/watcher.cjs +365 -354
- package/src/bin/cli/history.cjs +31 -31
- package/src/bin/cli/inspect.js +581 -581
- package/src/bin/cli/network.js +695 -695
- package/src/bin/cli/nodes.js +424 -424
- package/src/bin/cli/radon.js +1124 -1122
- package/src/bin/cli/wallet.js +1362 -1362
- package/src/bin/helpers.js +974 -974
- package/src/bin/index.js +328 -328
package/src/bin/helpers.js
CHANGED
|
@@ -1,974 +1,974 @@
|
|
|
1
|
-
import { exec } from "node:child_process";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
import * as net from "node:net";
|
|
4
|
-
import * as os from "node:os";
|
|
5
|
-
import * as readline from "node:readline";
|
|
6
|
-
import moment from "moment";
|
|
7
|
-
|
|
8
|
-
const require = createRequire(import.meta.url);
|
|
9
|
-
|
|
10
|
-
export const colorstrip = (str) =>
|
|
11
|
-
str.replace(
|
|
12
|
-
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
|
|
13
|
-
"",
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
export const commas = (number) => {
|
|
17
|
-
const parts = number.toString().split(".");
|
|
18
|
-
const result =
|
|
19
|
-
parts.length <= 1
|
|
20
|
-
? `${parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`
|
|
21
|
-
: `${parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",")}.${parts[1]}`;
|
|
22
|
-
return result;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export function toFixedTrunc(x, n) {
|
|
26
|
-
const v = (typeof x === "string" ? x : x.toString()).split(".");
|
|
27
|
-
if (n <= 0) return v[0];
|
|
28
|
-
let f = v[1] || "";
|
|
29
|
-
if (f.length > n) return `${v[0]}.${f.substr(0, n)}`;
|
|
30
|
-
while (f.length < n) f += "0";
|
|
31
|
-
return `${v[0]}.${f}`;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export const whole_wits = (number, digits) => {
|
|
35
|
-
const lookup = [
|
|
36
|
-
{ value: 1n, symbol: "pedros" },
|
|
37
|
-
{ value: 10n ** 6n, symbol: "mWits" },
|
|
38
|
-
{ value: 10n ** 9n, symbol: " Wits" },
|
|
39
|
-
{ value: 10n ** 12n, symbol: "KWits" },
|
|
40
|
-
{ value: 10n ** 15n, symbol: "MWits" },
|
|
41
|
-
];
|
|
42
|
-
// const regexp = /\.0+$|(?<=\.[0-9])0+$/
|
|
43
|
-
const item = lookup.findLast((item) => number >= item.value);
|
|
44
|
-
const quotient = item
|
|
45
|
-
? Number(BigInt(number) / item.value)
|
|
46
|
-
: number.toString();
|
|
47
|
-
const decimals = item
|
|
48
|
-
? (item.value + BigInt(number) - BigInt(quotient) * item.value)
|
|
49
|
-
.toString()
|
|
50
|
-
.slice(1)
|
|
51
|
-
: "";
|
|
52
|
-
return item
|
|
53
|
-
? `${commas(quotient)}${decimals !== "" ? `.${decimals.slice(0, digits)}` : ""} ${item.symbol}`
|
|
54
|
-
: "(no coins)";
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const bblue = (str) => `\x1b[1;98;44m${str}\x1b[0;0;0m`;
|
|
58
|
-
const bcyan = (str) => `\x1b[38;46m${str}\x1b[0;0m`;
|
|
59
|
-
const bgreen = (str) => `\x1b[30;42m${str}\x1b[0;0m`;
|
|
60
|
-
const bred = (str) => `\x1b[30;41m${str}\x1b[0;0m`;
|
|
61
|
-
const bviolet = (str) => `\x1b[30;45m${str}\x1b[0;0m`;
|
|
62
|
-
|
|
63
|
-
const lcyan = (str) => `\x1b[1;96m${str}\x1b[0m`;
|
|
64
|
-
const lgray = (str) => `\x1b[1;90m${str}\x1b[0m`;
|
|
65
|
-
const lgreen = (str) => `\x1b[1;92m${str}\x1b[0m`;
|
|
66
|
-
const lmagenta = (str) => `\x1b[1;95m${str}\x1b[0m`;
|
|
67
|
-
const lyellow = (str) => `\x1b[1;93m${str}\x1b[0m`;
|
|
68
|
-
const mblue = (str) => `\x1b[94m${str}\x1b[0m`;
|
|
69
|
-
const mcyan = (str) => `\x1b[96m${str}\x1b[0m`;
|
|
70
|
-
const mgreen = (str) => `\x1b[92m${str}\x1b[0m`;
|
|
71
|
-
const mmagenta = (str) => `\x1b[0;95m${str}\x1b[0m`;
|
|
72
|
-
const mred = (str) => `\x1b[91m${str}\x1b[0m`;
|
|
73
|
-
const myellow = (str) => `\x1b[93m${str}\x1b[0m`;
|
|
74
|
-
|
|
75
|
-
const blue = (str) => `\x1b[34m${str}\x1b[0m`;
|
|
76
|
-
const cyan = (str) => `\x1b[36m${str}\x1b[0m`;
|
|
77
|
-
const gray = (str) => `\x1b[90m${str}\x1b[0m`;
|
|
78
|
-
const green = (str) => `\x1b[32m${str}\x1b[0m`;
|
|
79
|
-
const magenta = (str) => `\x1b[0;35m${str}\x1b[0m`;
|
|
80
|
-
const normal = (str) => `\x1b[98m${str}\x1b[0m`;
|
|
81
|
-
const red = (str) => `\x1b[31m${str}\x1b[0m`;
|
|
82
|
-
const white = (str) => `\x1b[1;98m${str}\x1b[0m`;
|
|
83
|
-
const yellow = (str) => `\x1b[33m${str}\x1b[0m`;
|
|
84
|
-
|
|
85
|
-
export const colors = {
|
|
86
|
-
bblue,
|
|
87
|
-
bcyan,
|
|
88
|
-
bgreen,
|
|
89
|
-
bred,
|
|
90
|
-
bviolet,
|
|
91
|
-
lcyan,
|
|
92
|
-
lgray,
|
|
93
|
-
lgreen,
|
|
94
|
-
lmagenta,
|
|
95
|
-
lyellow,
|
|
96
|
-
mblue,
|
|
97
|
-
mcyan,
|
|
98
|
-
mgreen,
|
|
99
|
-
mmagenta,
|
|
100
|
-
mred,
|
|
101
|
-
myellow,
|
|
102
|
-
blue,
|
|
103
|
-
cyan,
|
|
104
|
-
gray,
|
|
105
|
-
green,
|
|
106
|
-
magenta,
|
|
107
|
-
normal,
|
|
108
|
-
red,
|
|
109
|
-
white,
|
|
110
|
-
yellow,
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
export function countLeaves(t, obj) {
|
|
114
|
-
if (!obj || typeof obj === "string") return 0;
|
|
115
|
-
if (obj instanceof t) return 1;
|
|
116
|
-
if (Array.isArray(obj))
|
|
117
|
-
return obj.reduce((sum, item) => sum + countLeaves(t, item), 0);
|
|
118
|
-
else
|
|
119
|
-
return Object.values(obj).reduce(
|
|
120
|
-
(sum, item) => sum + countLeaves(t, item),
|
|
121
|
-
0,
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export function deleteExtraFlags(args) {
|
|
126
|
-
return args.filter((arg) => !arg.startsWith("--"));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function cmd(...command) {
|
|
130
|
-
return new Promise((resolve, reject) => {
|
|
131
|
-
exec(
|
|
132
|
-
command.join(" "),
|
|
133
|
-
{ maxBuffer: 1024 * 1024 * 10 },
|
|
134
|
-
(error, stdout, stderr) => {
|
|
135
|
-
if (error) {
|
|
136
|
-
reject(error);
|
|
137
|
-
}
|
|
138
|
-
if (stderr) {
|
|
139
|
-
reject(stderr);
|
|
140
|
-
}
|
|
141
|
-
resolve(stdout);
|
|
142
|
-
},
|
|
143
|
-
);
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export async function execRadonBytecode(bytecode, ...flags) {
|
|
148
|
-
if (!isHexString(bytecode)) {
|
|
149
|
-
throw EvalError("invalid hex string");
|
|
150
|
-
} else {
|
|
151
|
-
const npx = os.type() === "Windows_NT" ? "npx.cmd" : "npx";
|
|
152
|
-
return cmd(npx, "witsdk", "radon", "dry-run", bytecode, ...flags);
|
|
153
|
-
// .catch((err) => {
|
|
154
|
-
// let errorMessage = err.message.split('\n').slice(1).join('\n').trim()
|
|
155
|
-
// const errorRegex = /.*^error: (?<message>.*)$.*/gm
|
|
156
|
-
// const matched = errorRegex.exec(err.message)
|
|
157
|
-
// if (matched) {
|
|
158
|
-
// errorMessage = matched.groups.message
|
|
159
|
-
// }
|
|
160
|
-
// console.log(errorMessage || err)
|
|
161
|
-
// console.error(errorMessage || err)
|
|
162
|
-
// })
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export function extractFromArgs(args, flags) {
|
|
167
|
-
const curated = {};
|
|
168
|
-
if (args && flags) {
|
|
169
|
-
Object.keys(flags).forEach((flag) => {
|
|
170
|
-
const flagIndex = args.indexOf(`--${flag}`);
|
|
171
|
-
if (flagIndex >= 0) {
|
|
172
|
-
if (flags[flag].param) {
|
|
173
|
-
curated[flag] = args[flagIndex];
|
|
174
|
-
if (!args[flagIndex + 1] || args[flagIndex + 1].startsWith("--")) {
|
|
175
|
-
throw Error(`Missing required parameter for --${flag}`);
|
|
176
|
-
} else {
|
|
177
|
-
curated[flag] = args[flagIndex + 1];
|
|
178
|
-
args.splice(flagIndex, 2);
|
|
179
|
-
}
|
|
180
|
-
} else {
|
|
181
|
-
curated[flag] = true;
|
|
182
|
-
args.splice(flagIndex, 1);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
return [args, curated];
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export function fromHexString(hexString) {
|
|
191
|
-
if (hexString.startsWith("0x")) hexString = hexString.slice(2);
|
|
192
|
-
return Uint8Array.from(
|
|
193
|
-
hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)),
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
export function ipIsPrivateOrLocalhost(ip) {
|
|
198
|
-
if (ip.substring(0, 7) === "::ffff:") {
|
|
199
|
-
ip = ip.substring(7);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (net.isIPv4(ip)) {
|
|
203
|
-
// check localhost
|
|
204
|
-
if (ip === "127.0.0.1") {
|
|
205
|
-
return true;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// 10.0.0.0 - 10.255.255.255 || 172.16.0.0 - 172.31.255.255 || 192.168.0.0 - 192.168.255.255
|
|
209
|
-
return (
|
|
210
|
-
/^(10)\.(.*)\.(.*)\.(.*)$/.test(ip) ||
|
|
211
|
-
/^(172)\.(1[6-9]|2[0-9]|3[0-1])\.(.*)\.(.*)$/.test(ip) ||
|
|
212
|
-
/^(192)\.(168)\.(.*)\.(.*)$/.test(ip)
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// else: ip is IPv6
|
|
217
|
-
const firstWord = ip.split(":").find((el) => !!el); // get first not empty word
|
|
218
|
-
|
|
219
|
-
// equivalent of 127.0.0.1 in IPv6
|
|
220
|
-
if (ip === "::1") return true;
|
|
221
|
-
// The original IPv6 Site Local addresses (fec0::/10) are deprecated. Range: fec0 - feff
|
|
222
|
-
else if (/^fe[c-f][0-f]$/.test(firstWord)) return true;
|
|
223
|
-
// These days Unique Local Addresses (ULA) are used in place of Site Local.
|
|
224
|
-
// Range: fc00 - fcff
|
|
225
|
-
else if (/^fc[0-f]{2}$/.test(firstWord)) return true;
|
|
226
|
-
// Range: fd00 - fcff
|
|
227
|
-
else if (/^fd[0-f]{2}$/.test(firstWord)) return true;
|
|
228
|
-
// Link local addresses (prefixed with fe80) are not routable
|
|
229
|
-
else if (firstWord === "fe80") return true;
|
|
230
|
-
// Discard Prefix
|
|
231
|
-
else if (firstWord === "100") return true;
|
|
232
|
-
|
|
233
|
-
// Any other IP address is not Unique Local Address (ULA)
|
|
234
|
-
return false;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
export function isHexStringOfLength(str, length) {
|
|
238
|
-
return (
|
|
239
|
-
(isHexString(str) &&
|
|
240
|
-
((str.startsWith("0x") && str.slice(2).length === length * 2) ||
|
|
241
|
-
str.length === length * 2)) ||
|
|
242
|
-
isWildcard(str)
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
export function isHexString(str) {
|
|
247
|
-
return (
|
|
248
|
-
(typeof str === "string" &&
|
|
249
|
-
((str.startsWith("0x") && /^[a-fA-F0-9]+$/i.test(str.slice(2))) ||
|
|
250
|
-
/^[a-fA-F0-9]+$/i.test(str))) ||
|
|
251
|
-
isWildcard(str)
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
export function toHexString(buffer, prefix0x = false) {
|
|
256
|
-
if (buffer instanceof Uint8Array) buffer = Buffer.from(buffer);
|
|
257
|
-
return (
|
|
258
|
-
(prefix0x ? "0x" : "") +
|
|
259
|
-
Array.prototype.map
|
|
260
|
-
.call(buffer, (x) => `00${x.toString(16)}`.slice(-2))
|
|
261
|
-
.join("")
|
|
262
|
-
.match(/[a-fA-F0-9]{2}/g)
|
|
263
|
-
.join("")
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
export function parseURL(url) {
|
|
268
|
-
try {
|
|
269
|
-
const parsedUrl = new URL(url);
|
|
270
|
-
return [
|
|
271
|
-
`${parsedUrl.protocol}//`,
|
|
272
|
-
parsedUrl.host,
|
|
273
|
-
parsedUrl.pathname.slice(1),
|
|
274
|
-
parsedUrl.search.slice(1),
|
|
275
|
-
];
|
|
276
|
-
} catch {
|
|
277
|
-
throw new TypeError(`Invalid URL was provided: ${url}`);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
export function showUsage(cmd, module) {
|
|
282
|
-
showUsageHeadline(cmd);
|
|
283
|
-
showUsageOptions({ ...module?.flags });
|
|
284
|
-
showUsageFlags({ ...module?.flags });
|
|
285
|
-
showUsageRouter({ ...module?.router });
|
|
286
|
-
showUsageEnvars({ ...module?.envars });
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
export function showUsageRouter(router) {
|
|
290
|
-
const cmds = Object.entries(router);
|
|
291
|
-
if (cmds.length > 0) {
|
|
292
|
-
console.info("\nSUBCOMMANDS:");
|
|
293
|
-
const maxLength = Math.max(...cmds.map(([cmd]) => cmd.length));
|
|
294
|
-
cmds.forEach((cmd) => {
|
|
295
|
-
console.info(
|
|
296
|
-
" ",
|
|
297
|
-
`${cmd[0]}${" ".repeat(maxLength - cmd[0].length)}`,
|
|
298
|
-
" ",
|
|
299
|
-
cmd[1].hint,
|
|
300
|
-
);
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
export function showUsageError(cmd, subcmd, module, error, flags) {
|
|
306
|
-
showUsageSubcommand(cmd, subcmd, module, error);
|
|
307
|
-
if (error) {
|
|
308
|
-
console.info("\nERROR:");
|
|
309
|
-
if (flags?.debug) {
|
|
310
|
-
console.error(error);
|
|
311
|
-
} else {
|
|
312
|
-
console.error(colors.red(error?.stack?.split("\n")[0] || error));
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
export function showUsageEnvars(envars) {
|
|
318
|
-
if (envars) {
|
|
319
|
-
envars = Object.entries(envars);
|
|
320
|
-
if (envars.length > 0) {
|
|
321
|
-
console.info("\nENVARS:");
|
|
322
|
-
const maxWidth = Math.max(...envars.map(([envar]) => envar.length));
|
|
323
|
-
envars.forEach(([envar, hint]) => {
|
|
324
|
-
if (envar.toUpperCase().indexOf("KEY") < 0 && process.env[envar]) {
|
|
325
|
-
console.info(
|
|
326
|
-
" ",
|
|
327
|
-
`${yellow(envar.toUpperCase())}${" ".repeat(maxWidth - envar.length)}`,
|
|
328
|
-
` => Settled to "${myellow(process.env[envar])}"`,
|
|
329
|
-
);
|
|
330
|
-
} else {
|
|
331
|
-
console.info(
|
|
332
|
-
" ",
|
|
333
|
-
`${yellow(envar.toUpperCase())}${" ".repeat(maxWidth - envar.length)}`,
|
|
334
|
-
` ${hint}`,
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
export function showUsageFlags(flags) {
|
|
343
|
-
if (flags) {
|
|
344
|
-
flags = Object.entries(flags)
|
|
345
|
-
.filter(([, flag]) => !flag?.param)
|
|
346
|
-
.sort(([a], [b]) => {
|
|
347
|
-
if (a < b) return -1;
|
|
348
|
-
else if (a > b) return 1;
|
|
349
|
-
else return 0;
|
|
350
|
-
});
|
|
351
|
-
if (flags.length > 0) {
|
|
352
|
-
console.info("\nFLAGS:");
|
|
353
|
-
const maxLength = Math.max(
|
|
354
|
-
...flags
|
|
355
|
-
.filter(([, { hint }]) => hint)
|
|
356
|
-
.map(([key, { param }]) =>
|
|
357
|
-
param ? key.length + param.length + 3 : key.length,
|
|
358
|
-
),
|
|
359
|
-
);
|
|
360
|
-
flags.forEach((flag) => {
|
|
361
|
-
const str = `${flag[0]}${flag[1].param ? gray(` <${flag[1].param}>`) : ""}`;
|
|
362
|
-
if (flag[1].hint) {
|
|
363
|
-
console.info(
|
|
364
|
-
" ",
|
|
365
|
-
`--${str}${" ".repeat(maxLength - colorstrip(str).length)}`,
|
|
366
|
-
" ",
|
|
367
|
-
flag[1].hint,
|
|
368
|
-
);
|
|
369
|
-
}
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
export function showUsageHeadline(cmd, subcmd, module) {
|
|
376
|
-
console.info("USAGE:");
|
|
377
|
-
if (subcmd) {
|
|
378
|
-
let params = module.router[subcmd]?.params;
|
|
379
|
-
// const options = module.router[subcmd]?.options
|
|
380
|
-
if (params) {
|
|
381
|
-
const optionalize = (str) =>
|
|
382
|
-
str.endsWith(" ...]")
|
|
383
|
-
? `[<${str.slice(1, -5)}> ...]`
|
|
384
|
-
: str[0] === "["
|
|
385
|
-
? `[<${str.slice(1, -1)}>]`
|
|
386
|
-
: `<${str}>`;
|
|
387
|
-
if (Array.isArray(params)) {
|
|
388
|
-
params = `${params.map((param) => optionalize(param)).join(" ")} `;
|
|
389
|
-
} else {
|
|
390
|
-
params = optionalize(params);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
console.info(
|
|
394
|
-
` ${colors.white(`npx witsdk ${cmd}`)} ${colors.white(subcmd)} ${params ? `${colors.green(params)} ` : ""}[OPTIONS] [FLAGS]`,
|
|
395
|
-
);
|
|
396
|
-
if (module?.router[subcmd]?.hint) {
|
|
397
|
-
console.info("\nDESCRIPTION:");
|
|
398
|
-
console.info(` ${module.router[subcmd].hint}`);
|
|
399
|
-
}
|
|
400
|
-
} else {
|
|
401
|
-
console.info(
|
|
402
|
-
` ${colors.white(`npx witsdk ${cmd}`)} <SUBCOMMAND> ... [OPTIONS] [FLAGS]`,
|
|
403
|
-
);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
export function showUsageOptions(options) {
|
|
408
|
-
options = Object.entries(options)
|
|
409
|
-
.filter(([, option]) => option?.param)
|
|
410
|
-
.sort(([a], [b]) => {
|
|
411
|
-
if (a < b) return -1;
|
|
412
|
-
else if (a > b) return 1;
|
|
413
|
-
else return 0;
|
|
414
|
-
});
|
|
415
|
-
if (options.length > 0) {
|
|
416
|
-
console.info("\nOPTIONS:");
|
|
417
|
-
const maxLength = options
|
|
418
|
-
.map((option) =>
|
|
419
|
-
option[1].param
|
|
420
|
-
? option[1].param.length + option[0].length + 3
|
|
421
|
-
: option[0].length,
|
|
422
|
-
)
|
|
423
|
-
.reduce((prev, curr) => (curr > prev ? curr : prev));
|
|
424
|
-
options.forEach((option) => {
|
|
425
|
-
if (option[1].hint) {
|
|
426
|
-
const str = `${option[0]}${option[1].param ? gray(` <${option[1].param}>`) : ""}`;
|
|
427
|
-
console.info(
|
|
428
|
-
" ",
|
|
429
|
-
`--${str}${" ".repeat(maxLength - colorstrip(str).length)}`,
|
|
430
|
-
" ",
|
|
431
|
-
option[1].hint,
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
export function showUsageSubcommand(cmd, subcmd, module) {
|
|
439
|
-
showUsageHeadline(cmd, subcmd, module);
|
|
440
|
-
showUsageOptions({ ...module?.flags, ...module.router[subcmd]?.options });
|
|
441
|
-
showUsageFlags({ ...module?.flags, ...module.router[subcmd]?.options });
|
|
442
|
-
showUsageEnvars(module.router[subcmd]?.envars || module?.envars);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
export function showVersion() {
|
|
446
|
-
console.info(
|
|
447
|
-
`${colors.mcyan(`Witnet SDK v${require("../../package.json").version}`)}`,
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
export function getWildcardsCountFromString(str) {
|
|
452
|
-
let maxArgsIndex = 0;
|
|
453
|
-
if (str && typeof str === "string") {
|
|
454
|
-
let match;
|
|
455
|
-
const regexp = /\\\d\\/g;
|
|
456
|
-
while ((match = regexp.exec(str)) !== null) {
|
|
457
|
-
const argsIndex = parseInt(match[0][1], 10) + 1;
|
|
458
|
-
if (argsIndex > maxArgsIndex) maxArgsIndex = argsIndex;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
return maxArgsIndex;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
export function checkRpcWildcards(wildcards) {
|
|
465
|
-
if (typeof wildcards === "object") {
|
|
466
|
-
Object.values(wildcards).forEach((wildcard) => {
|
|
467
|
-
if (Array.isArray(wildcard))
|
|
468
|
-
wildcard.forEach((item) => checkRpcWildcards(item));
|
|
469
|
-
else checkRpcWildcards(wildcard);
|
|
470
|
-
});
|
|
471
|
-
} else if (Array.isArray(wildcards)) {
|
|
472
|
-
wildcards.forEach((wildcard) => checkRpcWildcards(wildcard));
|
|
473
|
-
} else if (typeof wildcards === "string") {
|
|
474
|
-
if (isWildcard(wildcards)) {
|
|
475
|
-
const char = wildcards.charAt(1);
|
|
476
|
-
if (char < "0" || char > "9") {
|
|
477
|
-
throw Error("RPC: wildcards not in range [0 .. 9]");
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
export function isWildcard(str) {
|
|
484
|
-
return str.length === 3 && /\\\d\\/g.test(str);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
export function replaceWildcards(obj, args) {
|
|
488
|
-
if (args.length > 10) args = args.slice(0, 10);
|
|
489
|
-
if (obj && typeof obj === "string") {
|
|
490
|
-
for (let argIndex = 0; argIndex < args.length; argIndex++) {
|
|
491
|
-
const wildcard = `\\${argIndex}\\`;
|
|
492
|
-
obj = obj.replaceAll(wildcard, args[argIndex]);
|
|
493
|
-
}
|
|
494
|
-
} else if (obj && Array.isArray(obj)) {
|
|
495
|
-
obj = obj.map((value) =>
|
|
496
|
-
typeof value === "string" || Array.isArray(value)
|
|
497
|
-
? replaceWildcards(value, args)
|
|
498
|
-
: value,
|
|
499
|
-
);
|
|
500
|
-
} else if (obj && typeof obj === "object") {
|
|
501
|
-
obj = replaceObjectWildcards(obj, args);
|
|
502
|
-
}
|
|
503
|
-
return obj;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
export function replaceObjectWildcards(obj, args) {
|
|
507
|
-
return Object.fromEntries(
|
|
508
|
-
Object.entries(obj).map(([key, value]) => {
|
|
509
|
-
for (let argIndex = 0; argIndex < args.length; argIndex++) {
|
|
510
|
-
const wildcard = `\\${argIndex}\\`;
|
|
511
|
-
key = key.replaceAll(wildcard, args[argIndex]);
|
|
512
|
-
value = replaceWildcards(value, args);
|
|
513
|
-
}
|
|
514
|
-
return [key, value];
|
|
515
|
-
}),
|
|
516
|
-
);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
export function spliceWildcard(obj, argIndex, argValue, argsCount) {
|
|
520
|
-
if (obj && typeof obj === "string") {
|
|
521
|
-
const wildcard = `\\${argIndex}\\`;
|
|
522
|
-
obj = obj.replaceAll(wildcard, argValue);
|
|
523
|
-
for (let j = argIndex + 1; j < argsCount; j++) {
|
|
524
|
-
obj = obj.replaceAll(`\\${j}\\`, `\\${j - 1}\\`);
|
|
525
|
-
}
|
|
526
|
-
} else if (obj && Array.isArray(obj)) {
|
|
527
|
-
obj = obj.map((value) =>
|
|
528
|
-
typeof value === "string" || Array.isArray(value)
|
|
529
|
-
? spliceWildcard(value, argIndex, argValue, argsCount)
|
|
530
|
-
: value,
|
|
531
|
-
);
|
|
532
|
-
}
|
|
533
|
-
return obj;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
export async function toolkitRun(settings, args) {
|
|
537
|
-
const cmd = `${settings.paths.toolkitBinPath} ${args.join(" ")}`;
|
|
538
|
-
return new Promise((resolve, reject) => {
|
|
539
|
-
exec(cmd, { maxBuffer: 1024 * 1024 * 10 }, (error, stdout, stderr) => {
|
|
540
|
-
if (error) {
|
|
541
|
-
reject(error);
|
|
542
|
-
}
|
|
543
|
-
if (stderr) {
|
|
544
|
-
reject(stderr);
|
|
545
|
-
}
|
|
546
|
-
resolve(stdout);
|
|
547
|
-
});
|
|
548
|
-
});
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
export function toUpperCamelCase(str) {
|
|
552
|
-
return str
|
|
553
|
-
.replace(/\b(\w)/g, (_match, capture) => capture.toUpperCase())
|
|
554
|
-
.replace(/\s+/g, "");
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
export function toUtf16Bytes(str) {
|
|
558
|
-
const bytes = new Uint8Array(str.length * 2);
|
|
559
|
-
for (let i = 0; i < str.length; i++) {
|
|
560
|
-
const code = str.charCodeAt(i);
|
|
561
|
-
bytes[i * 2] = code >> 8;
|
|
562
|
-
bytes[i * 2 + 1] = code & 0xff;
|
|
563
|
-
}
|
|
564
|
-
return bytes;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
export function toUtf8Array(str) {
|
|
568
|
-
const utf8 = [];
|
|
569
|
-
for (let i = 0; i < str.length; i++) {
|
|
570
|
-
let charcode = str.charCodeAt(i);
|
|
571
|
-
if (charcode < 0x80) utf8.push(charcode);
|
|
572
|
-
else if (charcode < 0x800) {
|
|
573
|
-
utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));
|
|
574
|
-
} else if (charcode < 0xd800 || charcode >= 0xe000) {
|
|
575
|
-
utf8.push(
|
|
576
|
-
0xe0 | (charcode >> 12),
|
|
577
|
-
0x80 | ((charcode >> 6) & 0x3f),
|
|
578
|
-
0x80 | (charcode & 0x3f),
|
|
579
|
-
);
|
|
580
|
-
} else {
|
|
581
|
-
// surrogate pair
|
|
582
|
-
i++;
|
|
583
|
-
// UTF-16 encodes 0x10000-0x10FFFF by
|
|
584
|
-
// subtracting 0x10000 and splitting the
|
|
585
|
-
// 20 bits of 0x0-0xFFFFF into two halves
|
|
586
|
-
charcode =
|
|
587
|
-
0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
|
|
588
|
-
utf8.push(
|
|
589
|
-
0xf0 | (charcode >> 18),
|
|
590
|
-
0x80 | ((charcode >> 12) & 0x3f),
|
|
591
|
-
0x80 | ((charcode >> 6) & 0x3f),
|
|
592
|
-
0x80 | (charcode & 0x3f),
|
|
593
|
-
);
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
return utf8;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
export function utf8ArrayToStr(array) {
|
|
600
|
-
const len = array.length;
|
|
601
|
-
let out = "";
|
|
602
|
-
let i = 0;
|
|
603
|
-
let c;
|
|
604
|
-
let char2, char3;
|
|
605
|
-
while (i < len) {
|
|
606
|
-
c = array[i++];
|
|
607
|
-
switch (c >> 4) {
|
|
608
|
-
case 0:
|
|
609
|
-
case 1:
|
|
610
|
-
case 2:
|
|
611
|
-
case 3:
|
|
612
|
-
case 4:
|
|
613
|
-
case 5:
|
|
614
|
-
case 6:
|
|
615
|
-
case 7:
|
|
616
|
-
// 0xxxxxxx
|
|
617
|
-
out += String.fromCharCode(c);
|
|
618
|
-
break;
|
|
619
|
-
case 12:
|
|
620
|
-
case 13:
|
|
621
|
-
// 110x xxxx 10xx xxxx
|
|
622
|
-
char2 = array[i++];
|
|
623
|
-
out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f));
|
|
624
|
-
break;
|
|
625
|
-
case 14:
|
|
626
|
-
// 1110 xxxx 10xx xxxx 10xx xxxx
|
|
627
|
-
char2 = array[i++];
|
|
628
|
-
char3 = array[i++];
|
|
629
|
-
out += String.fromCharCode(
|
|
630
|
-
((c & 0x0f) << 12) | ((char2 & 0x3f) << 6) | ((char3 & 0x3f) << 0),
|
|
631
|
-
);
|
|
632
|
-
break;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
return out;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
export async function prompt(question) {
|
|
639
|
-
const readlineInterface = readline.createInterface({
|
|
640
|
-
input: process.stdin,
|
|
641
|
-
output: process.stdout,
|
|
642
|
-
});
|
|
643
|
-
return new Promise((resolve, _reject) => {
|
|
644
|
-
readlineInterface.question(`${question} `, (response) => {
|
|
645
|
-
readlineInterface.close();
|
|
646
|
-
resolve(response.trim());
|
|
647
|
-
});
|
|
648
|
-
});
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
export function prompter(promise) {
|
|
652
|
-
const loading = (() => {
|
|
653
|
-
const h = ["|", "/", "-", "\\"];
|
|
654
|
-
let i = 0;
|
|
655
|
-
return setInterval(() => {
|
|
656
|
-
i = i > 3 ? 0 : i;
|
|
657
|
-
process.stdout.write(`\b\b${h[i]} `);
|
|
658
|
-
i++;
|
|
659
|
-
}, 50);
|
|
660
|
-
})();
|
|
661
|
-
return promise.then((result) => {
|
|
662
|
-
clearInterval(loading);
|
|
663
|
-
process.stdout.write("\b\b");
|
|
664
|
-
return result;
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
export function traceChecklists(checklists) {
|
|
669
|
-
if (checklists && Object.keys(checklists).length > 0) {
|
|
670
|
-
const headlines = [
|
|
671
|
-
"NODES",
|
|
672
|
-
...Object.keys(checklists).map((key) => `:${key}`),
|
|
673
|
-
];
|
|
674
|
-
checklists = Object.values(checklists);
|
|
675
|
-
const urls = Object.keys(checklists[0]);
|
|
676
|
-
const records = urls.map((url) => {
|
|
677
|
-
const errors = checklists.filter(
|
|
678
|
-
(checklist) => checklist[url] instanceof Error,
|
|
679
|
-
).length;
|
|
680
|
-
return [
|
|
681
|
-
errors === checklists.length
|
|
682
|
-
? colors.red(url)
|
|
683
|
-
: errors > 0
|
|
684
|
-
? colors.myellow(url)
|
|
685
|
-
: colors.mcyan(url),
|
|
686
|
-
...checklists.map((checklist) =>
|
|
687
|
-
checklist[url] instanceof Error
|
|
688
|
-
? colors.red(checklist[url])
|
|
689
|
-
: checklist[url] === true
|
|
690
|
-
? colors.lcyan("Aye")
|
|
691
|
-
: colors.cyan("Nay"),
|
|
692
|
-
),
|
|
693
|
-
];
|
|
694
|
-
});
|
|
695
|
-
traceTable(records, {
|
|
696
|
-
headlines,
|
|
697
|
-
maxColumnWidth: 31,
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
export function traceHeader(headline, color = normal, indent = "") {
|
|
703
|
-
console.info(`${indent}┌─${"─".repeat(headline.length)}─┐`);
|
|
704
|
-
console.info(`${indent}│ ${color(headline)} │`);
|
|
705
|
-
console.info(`${indent}└─${"─".repeat(headline.length)}─┘`);
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
export function traceTable(records, options) {
|
|
709
|
-
const stringify = (data, humanizers, index) =>
|
|
710
|
-
humanizers?.[index]
|
|
711
|
-
? humanizers[index](data).toString()
|
|
712
|
-
: (data?.toString() ?? "");
|
|
713
|
-
const max = (a, b) => (a > b ? a : b);
|
|
714
|
-
const reduceMax = (numbers) =>
|
|
715
|
-
numbers.reduce((curr, prev) => (prev > curr ? prev : curr), 0);
|
|
716
|
-
if (!options) options = {};
|
|
717
|
-
const indent = options?.indent || "";
|
|
718
|
-
const numColumns = reduceMax(records.map((record) => record?.length || 1));
|
|
719
|
-
const maxColumnWidth = options?.maxColumnWidth || 80;
|
|
720
|
-
const table = transpose(records, numColumns);
|
|
721
|
-
options.widths =
|
|
722
|
-
options?.widths ||
|
|
723
|
-
table.map((column, index) => {
|
|
724
|
-
let maxWidth = reduceMax(
|
|
725
|
-
column.map(
|
|
726
|
-
(field) =>
|
|
727
|
-
colorstrip(stringify(field, options?.humanizers, index)).length,
|
|
728
|
-
),
|
|
729
|
-
);
|
|
730
|
-
if (options?.headlines?.[index]) {
|
|
731
|
-
maxWidth = max(
|
|
732
|
-
maxWidth,
|
|
733
|
-
colorstrip(options.headlines[index].replaceAll(":", "")).length,
|
|
734
|
-
);
|
|
735
|
-
}
|
|
736
|
-
return Math.min(maxWidth, maxColumnWidth);
|
|
737
|
-
});
|
|
738
|
-
let headline = options.widths.map((maxWidth) => "─".repeat(maxWidth));
|
|
739
|
-
console.info(`${indent}┌─${headline.join("─┬─")}─┐`);
|
|
740
|
-
if (options?.headlines) {
|
|
741
|
-
headline = options.widths.map((maxWidth, index) => {
|
|
742
|
-
const caption = options.headlines[index].replaceAll(":", "");
|
|
743
|
-
const captionLength = colorstrip(caption).length;
|
|
744
|
-
return `${white(caption)}${" ".repeat(maxWidth - captionLength)}`;
|
|
745
|
-
});
|
|
746
|
-
console.info(`${indent}│ ${headline.join(" │ ")} │`);
|
|
747
|
-
headline = options.widths.map((maxWidth) => "─".repeat(maxWidth));
|
|
748
|
-
console.info(`${indent}├─${headline.join("─┼─")}─┤`);
|
|
749
|
-
}
|
|
750
|
-
for (let i = 0; i < records.length; i++) {
|
|
751
|
-
let line = "";
|
|
752
|
-
for (let j = 0; j < numColumns; j++) {
|
|
753
|
-
let data = table[j][i];
|
|
754
|
-
let color;
|
|
755
|
-
if (options?.colors?.[j]) {
|
|
756
|
-
color = options.colors[j];
|
|
757
|
-
} else {
|
|
758
|
-
color =
|
|
759
|
-
typeof data === "string"
|
|
760
|
-
? green
|
|
761
|
-
: Number(data) === data && data % 1 !== 0 // is float number?
|
|
762
|
-
? yellow
|
|
763
|
-
: (x) => x;
|
|
764
|
-
}
|
|
765
|
-
data = stringify(data, options?.humanizers, j);
|
|
766
|
-
if (colorstrip(data).length > maxColumnWidth) {
|
|
767
|
-
while (colorstrip(data).length > maxColumnWidth - 3) {
|
|
768
|
-
data = data.slice(0, -1);
|
|
769
|
-
}
|
|
770
|
-
data += "...";
|
|
771
|
-
}
|
|
772
|
-
const dataLength = colorstrip(data).length;
|
|
773
|
-
if (options?.headlines && options.headlines[j][0] === ":") {
|
|
774
|
-
data = `${color(data)}${" ".repeat(options.widths[j] - dataLength)}`;
|
|
775
|
-
} else {
|
|
776
|
-
data = `${" ".repeat(options.widths[j] - dataLength)}${color(data)}`;
|
|
777
|
-
}
|
|
778
|
-
line += `│ ${data} `;
|
|
779
|
-
}
|
|
780
|
-
console.info(`${indent}${line}│`);
|
|
781
|
-
}
|
|
782
|
-
headline = options.widths.map((maxWidth) => "─".repeat(maxWidth));
|
|
783
|
-
console.info(`${indent}└─${headline.join("─┴─")}─┘`);
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
function transpose(records, numColumns) {
|
|
787
|
-
const columns = [];
|
|
788
|
-
for (let index = 0; index < numColumns; index++) {
|
|
789
|
-
columns.push(records.map((row) => row[index]));
|
|
790
|
-
}
|
|
791
|
-
return columns;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
export function txJsonReplacer(key, value) {
|
|
795
|
-
switch (key) {
|
|
796
|
-
case "bytes":
|
|
797
|
-
case "der":
|
|
798
|
-
return toHexString(value, true);
|
|
799
|
-
case "tx":
|
|
800
|
-
return JSON.stringify(value, txJsonReplacer);
|
|
801
|
-
case "change":
|
|
802
|
-
case "fees":
|
|
803
|
-
case "value":
|
|
804
|
-
return parseInt(value, 10) / 10 ** 9;
|
|
805
|
-
default:
|
|
806
|
-
return value;
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
export function txReceiptJsonReplacer(key, value) {
|
|
811
|
-
switch (key) {
|
|
812
|
-
case "bytes":
|
|
813
|
-
case "der":
|
|
814
|
-
return toHexString(value, true);
|
|
815
|
-
case "tx":
|
|
816
|
-
return JSON.stringify(value, txJsonReplacer);
|
|
817
|
-
case "change":
|
|
818
|
-
case "fees":
|
|
819
|
-
case "value":
|
|
820
|
-
return parseInt(value?.pedros, 10) / 10 ** 9;
|
|
821
|
-
case "timestamp":
|
|
822
|
-
return moment.unix(value).format("MMMM Do YYYY, h:mm:ss a");
|
|
823
|
-
default:
|
|
824
|
-
return value;
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
export function traceTransactionOnCheckpoint(receipt) {
|
|
829
|
-
if (receipt?.confirmations) {
|
|
830
|
-
console.info(` > Checkpoint #${commas(receipt.confirmations)}...`);
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
export function traceTransactionOnStatusChange(receipt) {
|
|
835
|
-
const captions = {
|
|
836
|
-
pending: "Awaiting relay...",
|
|
837
|
-
// confirmed: "Transaction confirmed:",
|
|
838
|
-
// finalized: "Transaction finalized:",
|
|
839
|
-
relayed: "Awaiting inclusion...",
|
|
840
|
-
mined: "Awaiting confirmations...",
|
|
841
|
-
};
|
|
842
|
-
const caption = captions[receipt.status];
|
|
843
|
-
if (caption) console.info(` > ${captions[receipt.status]}`);
|
|
844
|
-
if (["finalized", "confirmed"].includes(receipt.status)) {
|
|
845
|
-
console.info(` > Block hash: ${colors.gray(receipt?.blockHash)}`);
|
|
846
|
-
console.info(` > Block miner: ${colors.cyan(receipt?.blockMiner)}`);
|
|
847
|
-
console.info(
|
|
848
|
-
` > Block epoch: ${colors.white(commas(receipt?.blockEpoch))}`,
|
|
849
|
-
);
|
|
850
|
-
console.info(
|
|
851
|
-
` > Included at: ${colors.green(moment.unix(receipt?.blockTimestamp).format("MMMM Do YYYY, h:mm:ss a"))}`,
|
|
852
|
-
);
|
|
853
|
-
console.info(
|
|
854
|
-
` > ${receipt.status[0].toUpperCase() + receipt.status.slice(1)} at: ${colors.mgreen(moment.unix(receipt.timestamp).format("MMMM Do YYYY, h:mm:ss a"))}`,
|
|
855
|
-
);
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
export function traceTransactionReceipt(receipt) {
|
|
860
|
-
const captions = {
|
|
861
|
-
DataRequest: " > DRT hash: ",
|
|
862
|
-
ValueTransfer: " > VTT hash: ",
|
|
863
|
-
};
|
|
864
|
-
console.info(
|
|
865
|
-
`${captions[receipt.type] || " > TX hash: "}${colors.white(receipt.hash)}`,
|
|
866
|
-
);
|
|
867
|
-
if (receipt?.droHash)
|
|
868
|
-
console.info(` > DRO hash: ${colors.green(receipt.droHash)}`);
|
|
869
|
-
if (receipt?.radHash)
|
|
870
|
-
console.info(` > RAD hash: ${colors.mgreen(receipt.radHash)}`);
|
|
871
|
-
if (receipt?.droSLA)
|
|
872
|
-
console.info(` > SLA params: ${JSON.stringify(receipt.droSLA)}`);
|
|
873
|
-
if (receipt?.withdrawer) {
|
|
874
|
-
if (receipt?.validator) {
|
|
875
|
-
console.info(` > Validator: ${colors.mcyan(receipt.validator)}`);
|
|
876
|
-
}
|
|
877
|
-
console.info(` > Withdrawer: ${colors.mmagenta(receipt.withdrawer)}`);
|
|
878
|
-
} else {
|
|
879
|
-
const signers = Array.isArray(receipt.from) ? receipt.from : [receipt.from];
|
|
880
|
-
console.info(` > Signer/s: ${colors.mmagenta(signers[0])}`);
|
|
881
|
-
signers.slice(1).forEach((signer) => {
|
|
882
|
-
console.info(` ${colors.mmagenta(signer)}`);
|
|
883
|
-
});
|
|
884
|
-
}
|
|
885
|
-
if (receipt?.recipients) {
|
|
886
|
-
console.info(
|
|
887
|
-
` > Recipient/s: ${colors.mblue(
|
|
888
|
-
receipt.recipients.filter(
|
|
889
|
-
(pkh, index, array) => index === array.indexOf(pkh),
|
|
890
|
-
),
|
|
891
|
-
)}`,
|
|
892
|
-
);
|
|
893
|
-
}
|
|
894
|
-
if (receipt?.fees)
|
|
895
|
-
console.info(` > Network fee: ${colors.yellow(receipt.fees.toString(2))}`);
|
|
896
|
-
if (receipt?.value)
|
|
897
|
-
console.info(
|
|
898
|
-
` > Value: ${colors.myellow(receipt.value.toString(2))}`,
|
|
899
|
-
);
|
|
900
|
-
if (receipt?.weight)
|
|
901
|
-
console.info(` > Weight: ${colors.mgreen(commas(receipt.weight))}`);
|
|
902
|
-
if (receipt?.witnesses) {
|
|
903
|
-
console.info(` > Witnesses: ${receipt.witnesses}`);
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
export async function traceTransaction(transmitter, options) {
|
|
908
|
-
const color = options?.color || ((x) => `\x1b[30;45m${x}\x1b[0m`);
|
|
909
|
-
let receipt = await transmitter.signTransaction(options, options?.reload);
|
|
910
|
-
if (options?.verbose) {
|
|
911
|
-
console.info(`\n${gray(JSON.stringify(receipt.tx, txJsonReplacer))}`);
|
|
912
|
-
}
|
|
913
|
-
if (options?.headline) {
|
|
914
|
-
console.info(`\n ${color(` ${options.headline} `)}\n`);
|
|
915
|
-
}
|
|
916
|
-
traceTransactionReceipt(receipt);
|
|
917
|
-
if (!options?.force) {
|
|
918
|
-
// prompt user confirmation
|
|
919
|
-
console.info();
|
|
920
|
-
const answer = await require("inquirer").createPromptModule()([
|
|
921
|
-
{
|
|
922
|
-
message: "Send transaction?",
|
|
923
|
-
type: "confirm",
|
|
924
|
-
name: "continue",
|
|
925
|
-
default: false,
|
|
926
|
-
},
|
|
927
|
-
]);
|
|
928
|
-
if (!answer.continue) {
|
|
929
|
-
return receipt;
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
try {
|
|
933
|
-
console.info();
|
|
934
|
-
receipt = await transmitter.sendTransaction();
|
|
935
|
-
if (options?.await || options?.confirmations !== undefined) {
|
|
936
|
-
receipt = await transmitter.confirmTransaction(receipt.hash, {
|
|
937
|
-
confirmations: options?.confirmations || 0,
|
|
938
|
-
onCheckpoint: traceTransactionOnCheckpoint,
|
|
939
|
-
onStatusChange: traceTransactionOnStatusChange,
|
|
940
|
-
});
|
|
941
|
-
} else {
|
|
942
|
-
const data = {
|
|
943
|
-
status: receipt?.status,
|
|
944
|
-
timestamp: receipt?.timestamp || Math.floor(Date.now() / 1000),
|
|
945
|
-
};
|
|
946
|
-
console.info(data);
|
|
947
|
-
}
|
|
948
|
-
} catch (err) {
|
|
949
|
-
if (err?.inFlight && err.inFlight) {
|
|
950
|
-
console.info(
|
|
951
|
-
`\n${colors.gray(JSON.stringify(err.inFligt?.message, txReceiptJsonReplacer))}`,
|
|
952
|
-
);
|
|
953
|
-
}
|
|
954
|
-
throw err;
|
|
955
|
-
}
|
|
956
|
-
return receipt;
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
export function unescapeSlashes(str) {
|
|
960
|
-
// add another escaped slash if the string ends with an odd
|
|
961
|
-
// number of escaped slashes which will crash JSON.parse
|
|
962
|
-
let parsedStr = str.replace(/(^|[^\\])(\\\\)*\\$/, "$&\\");
|
|
963
|
-
|
|
964
|
-
// escape unescaped double quotes to prevent error with
|
|
965
|
-
// added double quotes in json string
|
|
966
|
-
parsedStr = parsedStr.replace(/(^|[^\\])((\\\\)*")/g, "$1\\$2");
|
|
967
|
-
|
|
968
|
-
try {
|
|
969
|
-
parsedStr = JSON.parse(`"${parsedStr}"`);
|
|
970
|
-
} catch (_e) {
|
|
971
|
-
return str;
|
|
972
|
-
}
|
|
973
|
-
return parsedStr;
|
|
974
|
-
}
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import * as net from "node:net";
|
|
4
|
+
import * as os from "node:os";
|
|
5
|
+
import * as readline from "node:readline";
|
|
6
|
+
import moment from "moment";
|
|
7
|
+
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
|
|
10
|
+
export const colorstrip = (str) =>
|
|
11
|
+
str.replace(
|
|
12
|
+
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
|
|
13
|
+
"",
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
export const commas = (number) => {
|
|
17
|
+
const parts = number.toString().split(".");
|
|
18
|
+
const result =
|
|
19
|
+
parts.length <= 1
|
|
20
|
+
? `${parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`
|
|
21
|
+
: `${parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",")}.${parts[1]}`;
|
|
22
|
+
return result;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export function toFixedTrunc(x, n) {
|
|
26
|
+
const v = (typeof x === "string" ? x : x.toString()).split(".");
|
|
27
|
+
if (n <= 0) return v[0];
|
|
28
|
+
let f = v[1] || "";
|
|
29
|
+
if (f.length > n) return `${v[0]}.${f.substr(0, n)}`;
|
|
30
|
+
while (f.length < n) f += "0";
|
|
31
|
+
return `${v[0]}.${f}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const whole_wits = (number, digits) => {
|
|
35
|
+
const lookup = [
|
|
36
|
+
{ value: 1n, symbol: "pedros" },
|
|
37
|
+
{ value: 10n ** 6n, symbol: "mWits" },
|
|
38
|
+
{ value: 10n ** 9n, symbol: " Wits" },
|
|
39
|
+
{ value: 10n ** 12n, symbol: "KWits" },
|
|
40
|
+
{ value: 10n ** 15n, symbol: "MWits" },
|
|
41
|
+
];
|
|
42
|
+
// const regexp = /\.0+$|(?<=\.[0-9])0+$/
|
|
43
|
+
const item = lookup.findLast((item) => number >= item.value);
|
|
44
|
+
const quotient = item
|
|
45
|
+
? Number(BigInt(number) / item.value)
|
|
46
|
+
: number.toString();
|
|
47
|
+
const decimals = item
|
|
48
|
+
? (item.value + BigInt(number) - BigInt(quotient) * item.value)
|
|
49
|
+
.toString()
|
|
50
|
+
.slice(1)
|
|
51
|
+
: "";
|
|
52
|
+
return item
|
|
53
|
+
? `${commas(quotient)}${decimals !== "" ? `.${decimals.slice(0, digits)}` : ""} ${item.symbol}`
|
|
54
|
+
: "(no coins)";
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const bblue = (str) => `\x1b[1;98;44m${str}\x1b[0;0;0m`;
|
|
58
|
+
const bcyan = (str) => `\x1b[38;46m${str}\x1b[0;0m`;
|
|
59
|
+
const bgreen = (str) => `\x1b[30;42m${str}\x1b[0;0m`;
|
|
60
|
+
const bred = (str) => `\x1b[30;41m${str}\x1b[0;0m`;
|
|
61
|
+
const bviolet = (str) => `\x1b[30;45m${str}\x1b[0;0m`;
|
|
62
|
+
|
|
63
|
+
const lcyan = (str) => `\x1b[1;96m${str}\x1b[0m`;
|
|
64
|
+
const lgray = (str) => `\x1b[1;90m${str}\x1b[0m`;
|
|
65
|
+
const lgreen = (str) => `\x1b[1;92m${str}\x1b[0m`;
|
|
66
|
+
const lmagenta = (str) => `\x1b[1;95m${str}\x1b[0m`;
|
|
67
|
+
const lyellow = (str) => `\x1b[1;93m${str}\x1b[0m`;
|
|
68
|
+
const mblue = (str) => `\x1b[94m${str}\x1b[0m`;
|
|
69
|
+
const mcyan = (str) => `\x1b[96m${str}\x1b[0m`;
|
|
70
|
+
const mgreen = (str) => `\x1b[92m${str}\x1b[0m`;
|
|
71
|
+
const mmagenta = (str) => `\x1b[0;95m${str}\x1b[0m`;
|
|
72
|
+
const mred = (str) => `\x1b[91m${str}\x1b[0m`;
|
|
73
|
+
const myellow = (str) => `\x1b[93m${str}\x1b[0m`;
|
|
74
|
+
|
|
75
|
+
const blue = (str) => `\x1b[34m${str}\x1b[0m`;
|
|
76
|
+
const cyan = (str) => `\x1b[36m${str}\x1b[0m`;
|
|
77
|
+
const gray = (str) => `\x1b[90m${str}\x1b[0m`;
|
|
78
|
+
const green = (str) => `\x1b[32m${str}\x1b[0m`;
|
|
79
|
+
const magenta = (str) => `\x1b[0;35m${str}\x1b[0m`;
|
|
80
|
+
const normal = (str) => `\x1b[98m${str}\x1b[0m`;
|
|
81
|
+
const red = (str) => `\x1b[31m${str}\x1b[0m`;
|
|
82
|
+
const white = (str) => `\x1b[1;98m${str}\x1b[0m`;
|
|
83
|
+
const yellow = (str) => `\x1b[33m${str}\x1b[0m`;
|
|
84
|
+
|
|
85
|
+
export const colors = {
|
|
86
|
+
bblue,
|
|
87
|
+
bcyan,
|
|
88
|
+
bgreen,
|
|
89
|
+
bred,
|
|
90
|
+
bviolet,
|
|
91
|
+
lcyan,
|
|
92
|
+
lgray,
|
|
93
|
+
lgreen,
|
|
94
|
+
lmagenta,
|
|
95
|
+
lyellow,
|
|
96
|
+
mblue,
|
|
97
|
+
mcyan,
|
|
98
|
+
mgreen,
|
|
99
|
+
mmagenta,
|
|
100
|
+
mred,
|
|
101
|
+
myellow,
|
|
102
|
+
blue,
|
|
103
|
+
cyan,
|
|
104
|
+
gray,
|
|
105
|
+
green,
|
|
106
|
+
magenta,
|
|
107
|
+
normal,
|
|
108
|
+
red,
|
|
109
|
+
white,
|
|
110
|
+
yellow,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export function countLeaves(t, obj) {
|
|
114
|
+
if (!obj || typeof obj === "string") return 0;
|
|
115
|
+
if (obj instanceof t) return 1;
|
|
116
|
+
if (Array.isArray(obj))
|
|
117
|
+
return obj.reduce((sum, item) => sum + countLeaves(t, item), 0);
|
|
118
|
+
else
|
|
119
|
+
return Object.values(obj).reduce(
|
|
120
|
+
(sum, item) => sum + countLeaves(t, item),
|
|
121
|
+
0,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function deleteExtraFlags(args) {
|
|
126
|
+
return args.filter((arg) => !arg.startsWith("--"));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function cmd(...command) {
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
exec(
|
|
132
|
+
command.join(" "),
|
|
133
|
+
{ maxBuffer: 1024 * 1024 * 10 },
|
|
134
|
+
(error, stdout, stderr) => {
|
|
135
|
+
if (error) {
|
|
136
|
+
reject(error);
|
|
137
|
+
}
|
|
138
|
+
if (stderr) {
|
|
139
|
+
reject(stderr);
|
|
140
|
+
}
|
|
141
|
+
resolve(stdout);
|
|
142
|
+
},
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export async function execRadonBytecode(bytecode, ...flags) {
|
|
148
|
+
if (!isHexString(bytecode)) {
|
|
149
|
+
throw EvalError("invalid hex string");
|
|
150
|
+
} else {
|
|
151
|
+
const npx = os.type() === "Windows_NT" ? "npx.cmd" : "npx";
|
|
152
|
+
return cmd(npx, "witsdk", "radon", "dry-run", bytecode, ...flags);
|
|
153
|
+
// .catch((err) => {
|
|
154
|
+
// let errorMessage = err.message.split('\n').slice(1).join('\n').trim()
|
|
155
|
+
// const errorRegex = /.*^error: (?<message>.*)$.*/gm
|
|
156
|
+
// const matched = errorRegex.exec(err.message)
|
|
157
|
+
// if (matched) {
|
|
158
|
+
// errorMessage = matched.groups.message
|
|
159
|
+
// }
|
|
160
|
+
// console.log(errorMessage || err)
|
|
161
|
+
// console.error(errorMessage || err)
|
|
162
|
+
// })
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function extractFromArgs(args, flags) {
|
|
167
|
+
const curated = {};
|
|
168
|
+
if (args && flags) {
|
|
169
|
+
Object.keys(flags).forEach((flag) => {
|
|
170
|
+
const flagIndex = args.indexOf(`--${flag}`);
|
|
171
|
+
if (flagIndex >= 0) {
|
|
172
|
+
if (flags[flag].param) {
|
|
173
|
+
curated[flag] = args[flagIndex];
|
|
174
|
+
if (!args[flagIndex + 1] || args[flagIndex + 1].startsWith("--")) {
|
|
175
|
+
throw Error(`Missing required parameter for --${flag}`);
|
|
176
|
+
} else {
|
|
177
|
+
curated[flag] = args[flagIndex + 1];
|
|
178
|
+
args.splice(flagIndex, 2);
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
curated[flag] = true;
|
|
182
|
+
args.splice(flagIndex, 1);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return [args, curated];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function fromHexString(hexString) {
|
|
191
|
+
if (hexString.startsWith("0x")) hexString = hexString.slice(2);
|
|
192
|
+
return Uint8Array.from(
|
|
193
|
+
hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)),
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function ipIsPrivateOrLocalhost(ip) {
|
|
198
|
+
if (ip.substring(0, 7) === "::ffff:") {
|
|
199
|
+
ip = ip.substring(7);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (net.isIPv4(ip)) {
|
|
203
|
+
// check localhost
|
|
204
|
+
if (ip === "127.0.0.1") {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 10.0.0.0 - 10.255.255.255 || 172.16.0.0 - 172.31.255.255 || 192.168.0.0 - 192.168.255.255
|
|
209
|
+
return (
|
|
210
|
+
/^(10)\.(.*)\.(.*)\.(.*)$/.test(ip) ||
|
|
211
|
+
/^(172)\.(1[6-9]|2[0-9]|3[0-1])\.(.*)\.(.*)$/.test(ip) ||
|
|
212
|
+
/^(192)\.(168)\.(.*)\.(.*)$/.test(ip)
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// else: ip is IPv6
|
|
217
|
+
const firstWord = ip.split(":").find((el) => !!el); // get first not empty word
|
|
218
|
+
|
|
219
|
+
// equivalent of 127.0.0.1 in IPv6
|
|
220
|
+
if (ip === "::1") return true;
|
|
221
|
+
// The original IPv6 Site Local addresses (fec0::/10) are deprecated. Range: fec0 - feff
|
|
222
|
+
else if (/^fe[c-f][0-f]$/.test(firstWord)) return true;
|
|
223
|
+
// These days Unique Local Addresses (ULA) are used in place of Site Local.
|
|
224
|
+
// Range: fc00 - fcff
|
|
225
|
+
else if (/^fc[0-f]{2}$/.test(firstWord)) return true;
|
|
226
|
+
// Range: fd00 - fcff
|
|
227
|
+
else if (/^fd[0-f]{2}$/.test(firstWord)) return true;
|
|
228
|
+
// Link local addresses (prefixed with fe80) are not routable
|
|
229
|
+
else if (firstWord === "fe80") return true;
|
|
230
|
+
// Discard Prefix
|
|
231
|
+
else if (firstWord === "100") return true;
|
|
232
|
+
|
|
233
|
+
// Any other IP address is not Unique Local Address (ULA)
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function isHexStringOfLength(str, length) {
|
|
238
|
+
return (
|
|
239
|
+
(isHexString(str) &&
|
|
240
|
+
((str.startsWith("0x") && str.slice(2).length === length * 2) ||
|
|
241
|
+
str.length === length * 2)) ||
|
|
242
|
+
isWildcard(str)
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function isHexString(str) {
|
|
247
|
+
return (
|
|
248
|
+
(typeof str === "string" &&
|
|
249
|
+
((str.startsWith("0x") && /^[a-fA-F0-9]+$/i.test(str.slice(2))) ||
|
|
250
|
+
/^[a-fA-F0-9]+$/i.test(str))) ||
|
|
251
|
+
isWildcard(str)
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export function toHexString(buffer, prefix0x = false) {
|
|
256
|
+
if (buffer instanceof Uint8Array) buffer = Buffer.from(buffer);
|
|
257
|
+
return (
|
|
258
|
+
(prefix0x ? "0x" : "") +
|
|
259
|
+
Array.prototype.map
|
|
260
|
+
.call(buffer, (x) => `00${x.toString(16)}`.slice(-2))
|
|
261
|
+
.join("")
|
|
262
|
+
.match(/[a-fA-F0-9]{2}/g)
|
|
263
|
+
.join("")
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function parseURL(url) {
|
|
268
|
+
try {
|
|
269
|
+
const parsedUrl = new URL(url);
|
|
270
|
+
return [
|
|
271
|
+
`${parsedUrl.protocol}//`,
|
|
272
|
+
parsedUrl.host,
|
|
273
|
+
parsedUrl.pathname.slice(1),
|
|
274
|
+
parsedUrl.search.slice(1),
|
|
275
|
+
];
|
|
276
|
+
} catch {
|
|
277
|
+
throw new TypeError(`Invalid URL was provided: ${url}`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function showUsage(cmd, module) {
|
|
282
|
+
showUsageHeadline(cmd);
|
|
283
|
+
showUsageOptions({ ...module?.flags });
|
|
284
|
+
showUsageFlags({ ...module?.flags });
|
|
285
|
+
showUsageRouter({ ...module?.router });
|
|
286
|
+
showUsageEnvars({ ...module?.envars });
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function showUsageRouter(router) {
|
|
290
|
+
const cmds = Object.entries(router);
|
|
291
|
+
if (cmds.length > 0) {
|
|
292
|
+
console.info("\nSUBCOMMANDS:");
|
|
293
|
+
const maxLength = Math.max(...cmds.map(([cmd]) => cmd.length));
|
|
294
|
+
cmds.forEach((cmd) => {
|
|
295
|
+
console.info(
|
|
296
|
+
" ",
|
|
297
|
+
`${cmd[0]}${" ".repeat(maxLength - cmd[0].length)}`,
|
|
298
|
+
" ",
|
|
299
|
+
cmd[1].hint,
|
|
300
|
+
);
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export function showUsageError(cmd, subcmd, module, error, flags) {
|
|
306
|
+
showUsageSubcommand(cmd, subcmd, module, error);
|
|
307
|
+
if (error) {
|
|
308
|
+
console.info("\nERROR:");
|
|
309
|
+
if (flags?.debug) {
|
|
310
|
+
console.error(error);
|
|
311
|
+
} else {
|
|
312
|
+
console.error(colors.red(error?.stack?.split("\n")[0] || error));
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export function showUsageEnvars(envars) {
|
|
318
|
+
if (envars) {
|
|
319
|
+
envars = Object.entries(envars);
|
|
320
|
+
if (envars.length > 0) {
|
|
321
|
+
console.info("\nENVARS:");
|
|
322
|
+
const maxWidth = Math.max(...envars.map(([envar]) => envar.length));
|
|
323
|
+
envars.forEach(([envar, hint]) => {
|
|
324
|
+
if (envar.toUpperCase().indexOf("KEY") < 0 && process.env[envar]) {
|
|
325
|
+
console.info(
|
|
326
|
+
" ",
|
|
327
|
+
`${yellow(envar.toUpperCase())}${" ".repeat(maxWidth - envar.length)}`,
|
|
328
|
+
` => Settled to "${myellow(process.env[envar])}"`,
|
|
329
|
+
);
|
|
330
|
+
} else {
|
|
331
|
+
console.info(
|
|
332
|
+
" ",
|
|
333
|
+
`${yellow(envar.toUpperCase())}${" ".repeat(maxWidth - envar.length)}`,
|
|
334
|
+
` ${hint}`,
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function showUsageFlags(flags) {
|
|
343
|
+
if (flags) {
|
|
344
|
+
flags = Object.entries(flags)
|
|
345
|
+
.filter(([, flag]) => !flag?.param)
|
|
346
|
+
.sort(([a], [b]) => {
|
|
347
|
+
if (a < b) return -1;
|
|
348
|
+
else if (a > b) return 1;
|
|
349
|
+
else return 0;
|
|
350
|
+
});
|
|
351
|
+
if (flags.length > 0) {
|
|
352
|
+
console.info("\nFLAGS:");
|
|
353
|
+
const maxLength = Math.max(
|
|
354
|
+
...flags
|
|
355
|
+
.filter(([, { hint }]) => hint)
|
|
356
|
+
.map(([key, { param }]) =>
|
|
357
|
+
param ? key.length + param.length + 3 : key.length,
|
|
358
|
+
),
|
|
359
|
+
);
|
|
360
|
+
flags.forEach((flag) => {
|
|
361
|
+
const str = `${flag[0]}${flag[1].param ? gray(` <${flag[1].param}>`) : ""}`;
|
|
362
|
+
if (flag[1].hint) {
|
|
363
|
+
console.info(
|
|
364
|
+
" ",
|
|
365
|
+
`--${str}${" ".repeat(maxLength - colorstrip(str).length)}`,
|
|
366
|
+
" ",
|
|
367
|
+
flag[1].hint,
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function showUsageHeadline(cmd, subcmd, module) {
|
|
376
|
+
console.info("USAGE:");
|
|
377
|
+
if (subcmd) {
|
|
378
|
+
let params = module.router[subcmd]?.params;
|
|
379
|
+
// const options = module.router[subcmd]?.options
|
|
380
|
+
if (params) {
|
|
381
|
+
const optionalize = (str) =>
|
|
382
|
+
str.endsWith(" ...]")
|
|
383
|
+
? `[<${str.slice(1, -5)}> ...]`
|
|
384
|
+
: str[0] === "["
|
|
385
|
+
? `[<${str.slice(1, -1)}>]`
|
|
386
|
+
: `<${str}>`;
|
|
387
|
+
if (Array.isArray(params)) {
|
|
388
|
+
params = `${params.map((param) => optionalize(param)).join(" ")} `;
|
|
389
|
+
} else {
|
|
390
|
+
params = optionalize(params);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
console.info(
|
|
394
|
+
` ${colors.white(`npx witsdk ${cmd}`)} ${colors.white(subcmd)} ${params ? `${colors.green(params)} ` : ""}[OPTIONS] [FLAGS]`,
|
|
395
|
+
);
|
|
396
|
+
if (module?.router[subcmd]?.hint) {
|
|
397
|
+
console.info("\nDESCRIPTION:");
|
|
398
|
+
console.info(` ${module.router[subcmd].hint}`);
|
|
399
|
+
}
|
|
400
|
+
} else {
|
|
401
|
+
console.info(
|
|
402
|
+
` ${colors.white(`npx witsdk ${cmd}`)} <SUBCOMMAND> ... [OPTIONS] [FLAGS]`,
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
export function showUsageOptions(options) {
|
|
408
|
+
options = Object.entries(options)
|
|
409
|
+
.filter(([, option]) => option?.param)
|
|
410
|
+
.sort(([a], [b]) => {
|
|
411
|
+
if (a < b) return -1;
|
|
412
|
+
else if (a > b) return 1;
|
|
413
|
+
else return 0;
|
|
414
|
+
});
|
|
415
|
+
if (options.length > 0) {
|
|
416
|
+
console.info("\nOPTIONS:");
|
|
417
|
+
const maxLength = options
|
|
418
|
+
.map((option) =>
|
|
419
|
+
option[1].param
|
|
420
|
+
? option[1].param.length + option[0].length + 3
|
|
421
|
+
: option[0].length,
|
|
422
|
+
)
|
|
423
|
+
.reduce((prev, curr) => (curr > prev ? curr : prev));
|
|
424
|
+
options.forEach((option) => {
|
|
425
|
+
if (option[1].hint) {
|
|
426
|
+
const str = `${option[0]}${option[1].param ? gray(` <${option[1].param}>`) : ""}`;
|
|
427
|
+
console.info(
|
|
428
|
+
" ",
|
|
429
|
+
`--${str}${" ".repeat(maxLength - colorstrip(str).length)}`,
|
|
430
|
+
" ",
|
|
431
|
+
option[1].hint,
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export function showUsageSubcommand(cmd, subcmd, module) {
|
|
439
|
+
showUsageHeadline(cmd, subcmd, module);
|
|
440
|
+
showUsageOptions({ ...module?.flags, ...module.router[subcmd]?.options });
|
|
441
|
+
showUsageFlags({ ...module?.flags, ...module.router[subcmd]?.options });
|
|
442
|
+
showUsageEnvars(module.router[subcmd]?.envars || module?.envars);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export function showVersion() {
|
|
446
|
+
console.info(
|
|
447
|
+
`${colors.mcyan(`Witnet SDK v${require("../../package.json").version}`)}`,
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export function getWildcardsCountFromString(str) {
|
|
452
|
+
let maxArgsIndex = 0;
|
|
453
|
+
if (str && typeof str === "string") {
|
|
454
|
+
let match;
|
|
455
|
+
const regexp = /\\\d\\/g;
|
|
456
|
+
while ((match = regexp.exec(str)) !== null) {
|
|
457
|
+
const argsIndex = parseInt(match[0][1], 10) + 1;
|
|
458
|
+
if (argsIndex > maxArgsIndex) maxArgsIndex = argsIndex;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return maxArgsIndex;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export function checkRpcWildcards(wildcards) {
|
|
465
|
+
if (typeof wildcards === "object") {
|
|
466
|
+
Object.values(wildcards).forEach((wildcard) => {
|
|
467
|
+
if (Array.isArray(wildcard))
|
|
468
|
+
wildcard.forEach((item) => checkRpcWildcards(item));
|
|
469
|
+
else checkRpcWildcards(wildcard);
|
|
470
|
+
});
|
|
471
|
+
} else if (Array.isArray(wildcards)) {
|
|
472
|
+
wildcards.forEach((wildcard) => checkRpcWildcards(wildcard));
|
|
473
|
+
} else if (typeof wildcards === "string") {
|
|
474
|
+
if (isWildcard(wildcards)) {
|
|
475
|
+
const char = wildcards.charAt(1);
|
|
476
|
+
if (char < "0" || char > "9") {
|
|
477
|
+
throw Error("RPC: wildcards not in range [0 .. 9]");
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export function isWildcard(str) {
|
|
484
|
+
return str.length === 3 && /\\\d\\/g.test(str);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
export function replaceWildcards(obj, args) {
|
|
488
|
+
if (args.length > 10) args = args.slice(0, 10);
|
|
489
|
+
if (obj && typeof obj === "string") {
|
|
490
|
+
for (let argIndex = 0; argIndex < args.length; argIndex++) {
|
|
491
|
+
const wildcard = `\\${argIndex}\\`;
|
|
492
|
+
obj = obj.replaceAll(wildcard, args[argIndex]);
|
|
493
|
+
}
|
|
494
|
+
} else if (obj && Array.isArray(obj)) {
|
|
495
|
+
obj = obj.map((value) =>
|
|
496
|
+
typeof value === "string" || Array.isArray(value)
|
|
497
|
+
? replaceWildcards(value, args)
|
|
498
|
+
: value,
|
|
499
|
+
);
|
|
500
|
+
} else if (obj && typeof obj === "object") {
|
|
501
|
+
obj = replaceObjectWildcards(obj, args);
|
|
502
|
+
}
|
|
503
|
+
return obj;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
export function replaceObjectWildcards(obj, args) {
|
|
507
|
+
return Object.fromEntries(
|
|
508
|
+
Object.entries(obj).map(([key, value]) => {
|
|
509
|
+
for (let argIndex = 0; argIndex < args.length; argIndex++) {
|
|
510
|
+
const wildcard = `\\${argIndex}\\`;
|
|
511
|
+
key = key.replaceAll(wildcard, args[argIndex]);
|
|
512
|
+
value = replaceWildcards(value, args);
|
|
513
|
+
}
|
|
514
|
+
return [key, value];
|
|
515
|
+
}),
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
export function spliceWildcard(obj, argIndex, argValue, argsCount) {
|
|
520
|
+
if (obj && typeof obj === "string") {
|
|
521
|
+
const wildcard = `\\${argIndex}\\`;
|
|
522
|
+
obj = obj.replaceAll(wildcard, argValue);
|
|
523
|
+
for (let j = argIndex + 1; j < argsCount; j++) {
|
|
524
|
+
obj = obj.replaceAll(`\\${j}\\`, `\\${j - 1}\\`);
|
|
525
|
+
}
|
|
526
|
+
} else if (obj && Array.isArray(obj)) {
|
|
527
|
+
obj = obj.map((value) =>
|
|
528
|
+
typeof value === "string" || Array.isArray(value)
|
|
529
|
+
? spliceWildcard(value, argIndex, argValue, argsCount)
|
|
530
|
+
: value,
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
return obj;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
export async function toolkitRun(settings, args) {
|
|
537
|
+
const cmd = `${settings.paths.toolkitBinPath} ${args.join(" ")}`;
|
|
538
|
+
return new Promise((resolve, reject) => {
|
|
539
|
+
exec(cmd, { maxBuffer: 1024 * 1024 * 10 }, (error, stdout, stderr) => {
|
|
540
|
+
if (error) {
|
|
541
|
+
reject(error);
|
|
542
|
+
}
|
|
543
|
+
if (stderr) {
|
|
544
|
+
reject(stderr);
|
|
545
|
+
}
|
|
546
|
+
resolve(stdout);
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
export function toUpperCamelCase(str) {
|
|
552
|
+
return str
|
|
553
|
+
.replace(/\b(\w)/g, (_match, capture) => capture.toUpperCase())
|
|
554
|
+
.replace(/\s+/g, "");
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export function toUtf16Bytes(str) {
|
|
558
|
+
const bytes = new Uint8Array(str.length * 2);
|
|
559
|
+
for (let i = 0; i < str.length; i++) {
|
|
560
|
+
const code = str.charCodeAt(i);
|
|
561
|
+
bytes[i * 2] = code >> 8;
|
|
562
|
+
bytes[i * 2 + 1] = code & 0xff;
|
|
563
|
+
}
|
|
564
|
+
return bytes;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
export function toUtf8Array(str) {
|
|
568
|
+
const utf8 = [];
|
|
569
|
+
for (let i = 0; i < str.length; i++) {
|
|
570
|
+
let charcode = str.charCodeAt(i);
|
|
571
|
+
if (charcode < 0x80) utf8.push(charcode);
|
|
572
|
+
else if (charcode < 0x800) {
|
|
573
|
+
utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));
|
|
574
|
+
} else if (charcode < 0xd800 || charcode >= 0xe000) {
|
|
575
|
+
utf8.push(
|
|
576
|
+
0xe0 | (charcode >> 12),
|
|
577
|
+
0x80 | ((charcode >> 6) & 0x3f),
|
|
578
|
+
0x80 | (charcode & 0x3f),
|
|
579
|
+
);
|
|
580
|
+
} else {
|
|
581
|
+
// surrogate pair
|
|
582
|
+
i++;
|
|
583
|
+
// UTF-16 encodes 0x10000-0x10FFFF by
|
|
584
|
+
// subtracting 0x10000 and splitting the
|
|
585
|
+
// 20 bits of 0x0-0xFFFFF into two halves
|
|
586
|
+
charcode =
|
|
587
|
+
0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
|
|
588
|
+
utf8.push(
|
|
589
|
+
0xf0 | (charcode >> 18),
|
|
590
|
+
0x80 | ((charcode >> 12) & 0x3f),
|
|
591
|
+
0x80 | ((charcode >> 6) & 0x3f),
|
|
592
|
+
0x80 | (charcode & 0x3f),
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return utf8;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
export function utf8ArrayToStr(array) {
|
|
600
|
+
const len = array.length;
|
|
601
|
+
let out = "";
|
|
602
|
+
let i = 0;
|
|
603
|
+
let c;
|
|
604
|
+
let char2, char3;
|
|
605
|
+
while (i < len) {
|
|
606
|
+
c = array[i++];
|
|
607
|
+
switch (c >> 4) {
|
|
608
|
+
case 0:
|
|
609
|
+
case 1:
|
|
610
|
+
case 2:
|
|
611
|
+
case 3:
|
|
612
|
+
case 4:
|
|
613
|
+
case 5:
|
|
614
|
+
case 6:
|
|
615
|
+
case 7:
|
|
616
|
+
// 0xxxxxxx
|
|
617
|
+
out += String.fromCharCode(c);
|
|
618
|
+
break;
|
|
619
|
+
case 12:
|
|
620
|
+
case 13:
|
|
621
|
+
// 110x xxxx 10xx xxxx
|
|
622
|
+
char2 = array[i++];
|
|
623
|
+
out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f));
|
|
624
|
+
break;
|
|
625
|
+
case 14:
|
|
626
|
+
// 1110 xxxx 10xx xxxx 10xx xxxx
|
|
627
|
+
char2 = array[i++];
|
|
628
|
+
char3 = array[i++];
|
|
629
|
+
out += String.fromCharCode(
|
|
630
|
+
((c & 0x0f) << 12) | ((char2 & 0x3f) << 6) | ((char3 & 0x3f) << 0),
|
|
631
|
+
);
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return out;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export async function prompt(question) {
|
|
639
|
+
const readlineInterface = readline.createInterface({
|
|
640
|
+
input: process.stdin,
|
|
641
|
+
output: process.stdout,
|
|
642
|
+
});
|
|
643
|
+
return new Promise((resolve, _reject) => {
|
|
644
|
+
readlineInterface.question(`${question} `, (response) => {
|
|
645
|
+
readlineInterface.close();
|
|
646
|
+
resolve(response.trim());
|
|
647
|
+
});
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
export function prompter(promise) {
|
|
652
|
+
const loading = (() => {
|
|
653
|
+
const h = ["|", "/", "-", "\\"];
|
|
654
|
+
let i = 0;
|
|
655
|
+
return setInterval(() => {
|
|
656
|
+
i = i > 3 ? 0 : i;
|
|
657
|
+
process.stdout.write(`\b\b${h[i]} `);
|
|
658
|
+
i++;
|
|
659
|
+
}, 50);
|
|
660
|
+
})();
|
|
661
|
+
return promise.then((result) => {
|
|
662
|
+
clearInterval(loading);
|
|
663
|
+
process.stdout.write("\b\b");
|
|
664
|
+
return result;
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
export function traceChecklists(checklists) {
|
|
669
|
+
if (checklists && Object.keys(checklists).length > 0) {
|
|
670
|
+
const headlines = [
|
|
671
|
+
"NODES",
|
|
672
|
+
...Object.keys(checklists).map((key) => `:${key}`),
|
|
673
|
+
];
|
|
674
|
+
checklists = Object.values(checklists);
|
|
675
|
+
const urls = Object.keys(checklists[0]);
|
|
676
|
+
const records = urls.map((url) => {
|
|
677
|
+
const errors = checklists.filter(
|
|
678
|
+
(checklist) => checklist[url] instanceof Error,
|
|
679
|
+
).length;
|
|
680
|
+
return [
|
|
681
|
+
errors === checklists.length
|
|
682
|
+
? colors.red(url)
|
|
683
|
+
: errors > 0
|
|
684
|
+
? colors.myellow(url)
|
|
685
|
+
: colors.mcyan(url),
|
|
686
|
+
...checklists.map((checklist) =>
|
|
687
|
+
checklist[url] instanceof Error
|
|
688
|
+
? colors.red(checklist[url])
|
|
689
|
+
: checklist[url] === true
|
|
690
|
+
? colors.lcyan("Aye")
|
|
691
|
+
: colors.cyan("Nay"),
|
|
692
|
+
),
|
|
693
|
+
];
|
|
694
|
+
});
|
|
695
|
+
traceTable(records, {
|
|
696
|
+
headlines,
|
|
697
|
+
maxColumnWidth: 31,
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
export function traceHeader(headline, color = normal, indent = "") {
|
|
703
|
+
console.info(`${indent}┌─${"─".repeat(headline.length)}─┐`);
|
|
704
|
+
console.info(`${indent}│ ${color(headline)} │`);
|
|
705
|
+
console.info(`${indent}└─${"─".repeat(headline.length)}─┘`);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
export function traceTable(records, options) {
|
|
709
|
+
const stringify = (data, humanizers, index) =>
|
|
710
|
+
humanizers?.[index]
|
|
711
|
+
? humanizers[index](data).toString()
|
|
712
|
+
: (data?.toString() ?? "");
|
|
713
|
+
const max = (a, b) => (a > b ? a : b);
|
|
714
|
+
const reduceMax = (numbers) =>
|
|
715
|
+
numbers.reduce((curr, prev) => (prev > curr ? prev : curr), 0);
|
|
716
|
+
if (!options) options = {};
|
|
717
|
+
const indent = options?.indent || "";
|
|
718
|
+
const numColumns = reduceMax(records.map((record) => record?.length || 1));
|
|
719
|
+
const maxColumnWidth = options?.maxColumnWidth || 80;
|
|
720
|
+
const table = transpose(records, numColumns);
|
|
721
|
+
options.widths =
|
|
722
|
+
options?.widths ||
|
|
723
|
+
table.map((column, index) => {
|
|
724
|
+
let maxWidth = reduceMax(
|
|
725
|
+
column.map(
|
|
726
|
+
(field) =>
|
|
727
|
+
colorstrip(stringify(field, options?.humanizers, index)).length,
|
|
728
|
+
),
|
|
729
|
+
);
|
|
730
|
+
if (options?.headlines?.[index]) {
|
|
731
|
+
maxWidth = max(
|
|
732
|
+
maxWidth,
|
|
733
|
+
colorstrip(options.headlines[index].replaceAll(":", "")).length,
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
return Math.min(maxWidth, maxColumnWidth);
|
|
737
|
+
});
|
|
738
|
+
let headline = options.widths.map((maxWidth) => "─".repeat(maxWidth));
|
|
739
|
+
console.info(`${indent}┌─${headline.join("─┬─")}─┐`);
|
|
740
|
+
if (options?.headlines) {
|
|
741
|
+
headline = options.widths.map((maxWidth, index) => {
|
|
742
|
+
const caption = options.headlines[index].replaceAll(":", "");
|
|
743
|
+
const captionLength = colorstrip(caption).length;
|
|
744
|
+
return `${white(caption)}${" ".repeat(maxWidth - captionLength)}`;
|
|
745
|
+
});
|
|
746
|
+
console.info(`${indent}│ ${headline.join(" │ ")} │`);
|
|
747
|
+
headline = options.widths.map((maxWidth) => "─".repeat(maxWidth));
|
|
748
|
+
console.info(`${indent}├─${headline.join("─┼─")}─┤`);
|
|
749
|
+
}
|
|
750
|
+
for (let i = 0; i < records.length; i++) {
|
|
751
|
+
let line = "";
|
|
752
|
+
for (let j = 0; j < numColumns; j++) {
|
|
753
|
+
let data = table[j][i];
|
|
754
|
+
let color;
|
|
755
|
+
if (options?.colors?.[j]) {
|
|
756
|
+
color = options.colors[j];
|
|
757
|
+
} else {
|
|
758
|
+
color =
|
|
759
|
+
typeof data === "string"
|
|
760
|
+
? green
|
|
761
|
+
: Number(data) === data && data % 1 !== 0 // is float number?
|
|
762
|
+
? yellow
|
|
763
|
+
: (x) => x;
|
|
764
|
+
}
|
|
765
|
+
data = stringify(data, options?.humanizers, j);
|
|
766
|
+
if (colorstrip(data).length > maxColumnWidth) {
|
|
767
|
+
while (colorstrip(data).length > maxColumnWidth - 3) {
|
|
768
|
+
data = data.slice(0, -1);
|
|
769
|
+
}
|
|
770
|
+
data += "...";
|
|
771
|
+
}
|
|
772
|
+
const dataLength = colorstrip(data).length;
|
|
773
|
+
if (options?.headlines && options.headlines[j][0] === ":") {
|
|
774
|
+
data = `${color(data)}${" ".repeat(options.widths[j] - dataLength)}`;
|
|
775
|
+
} else {
|
|
776
|
+
data = `${" ".repeat(options.widths[j] - dataLength)}${color(data)}`;
|
|
777
|
+
}
|
|
778
|
+
line += `│ ${data} `;
|
|
779
|
+
}
|
|
780
|
+
console.info(`${indent}${line}│`);
|
|
781
|
+
}
|
|
782
|
+
headline = options.widths.map((maxWidth) => "─".repeat(maxWidth));
|
|
783
|
+
console.info(`${indent}└─${headline.join("─┴─")}─┘`);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
function transpose(records, numColumns) {
|
|
787
|
+
const columns = [];
|
|
788
|
+
for (let index = 0; index < numColumns; index++) {
|
|
789
|
+
columns.push(records.map((row) => row[index]));
|
|
790
|
+
}
|
|
791
|
+
return columns;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
export function txJsonReplacer(key, value) {
|
|
795
|
+
switch (key) {
|
|
796
|
+
case "bytes":
|
|
797
|
+
case "der":
|
|
798
|
+
return toHexString(value, true);
|
|
799
|
+
case "tx":
|
|
800
|
+
return JSON.stringify(value, txJsonReplacer);
|
|
801
|
+
case "change":
|
|
802
|
+
case "fees":
|
|
803
|
+
case "value":
|
|
804
|
+
return parseInt(value, 10) / 10 ** 9;
|
|
805
|
+
default:
|
|
806
|
+
return value;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
export function txReceiptJsonReplacer(key, value) {
|
|
811
|
+
switch (key) {
|
|
812
|
+
case "bytes":
|
|
813
|
+
case "der":
|
|
814
|
+
return toHexString(value, true);
|
|
815
|
+
case "tx":
|
|
816
|
+
return JSON.stringify(value, txJsonReplacer);
|
|
817
|
+
case "change":
|
|
818
|
+
case "fees":
|
|
819
|
+
case "value":
|
|
820
|
+
return parseInt(value?.pedros, 10) / 10 ** 9;
|
|
821
|
+
case "timestamp":
|
|
822
|
+
return moment.unix(value).format("MMMM Do YYYY, h:mm:ss a");
|
|
823
|
+
default:
|
|
824
|
+
return value;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
export function traceTransactionOnCheckpoint(receipt) {
|
|
829
|
+
if (receipt?.confirmations) {
|
|
830
|
+
console.info(` > Checkpoint #${commas(receipt.confirmations)}...`);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
export function traceTransactionOnStatusChange(receipt) {
|
|
835
|
+
const captions = {
|
|
836
|
+
pending: "Awaiting relay...",
|
|
837
|
+
// confirmed: "Transaction confirmed:",
|
|
838
|
+
// finalized: "Transaction finalized:",
|
|
839
|
+
relayed: "Awaiting inclusion...",
|
|
840
|
+
mined: "Awaiting confirmations...",
|
|
841
|
+
};
|
|
842
|
+
const caption = captions[receipt.status];
|
|
843
|
+
if (caption) console.info(` > ${captions[receipt.status]}`);
|
|
844
|
+
if (["finalized", "confirmed"].includes(receipt.status)) {
|
|
845
|
+
console.info(` > Block hash: ${colors.gray(receipt?.blockHash)}`);
|
|
846
|
+
console.info(` > Block miner: ${colors.cyan(receipt?.blockMiner)}`);
|
|
847
|
+
console.info(
|
|
848
|
+
` > Block epoch: ${colors.white(commas(receipt?.blockEpoch))}`,
|
|
849
|
+
);
|
|
850
|
+
console.info(
|
|
851
|
+
` > Included at: ${colors.green(moment.unix(receipt?.blockTimestamp).format("MMMM Do YYYY, h:mm:ss a"))}`,
|
|
852
|
+
);
|
|
853
|
+
console.info(
|
|
854
|
+
` > ${receipt.status[0].toUpperCase() + receipt.status.slice(1)} at: ${colors.mgreen(moment.unix(receipt.timestamp).format("MMMM Do YYYY, h:mm:ss a"))}`,
|
|
855
|
+
);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
export function traceTransactionReceipt(receipt) {
|
|
860
|
+
const captions = {
|
|
861
|
+
DataRequest: " > DRT hash: ",
|
|
862
|
+
ValueTransfer: " > VTT hash: ",
|
|
863
|
+
};
|
|
864
|
+
console.info(
|
|
865
|
+
`${captions[receipt.type] || " > TX hash: "}${colors.white(receipt.hash)}`,
|
|
866
|
+
);
|
|
867
|
+
if (receipt?.droHash)
|
|
868
|
+
console.info(` > DRO hash: ${colors.green(receipt.droHash)}`);
|
|
869
|
+
if (receipt?.radHash)
|
|
870
|
+
console.info(` > RAD hash: ${colors.mgreen(receipt.radHash)}`);
|
|
871
|
+
if (receipt?.droSLA)
|
|
872
|
+
console.info(` > SLA params: ${JSON.stringify(receipt.droSLA)}`);
|
|
873
|
+
if (receipt?.withdrawer) {
|
|
874
|
+
if (receipt?.validator) {
|
|
875
|
+
console.info(` > Validator: ${colors.mcyan(receipt.validator)}`);
|
|
876
|
+
}
|
|
877
|
+
console.info(` > Withdrawer: ${colors.mmagenta(receipt.withdrawer)}`);
|
|
878
|
+
} else {
|
|
879
|
+
const signers = Array.isArray(receipt.from) ? receipt.from : [receipt.from];
|
|
880
|
+
console.info(` > Signer/s: ${colors.mmagenta(signers[0])}`);
|
|
881
|
+
signers.slice(1).forEach((signer) => {
|
|
882
|
+
console.info(` ${colors.mmagenta(signer)}`);
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
if (receipt?.recipients) {
|
|
886
|
+
console.info(
|
|
887
|
+
` > Recipient/s: ${colors.mblue(
|
|
888
|
+
receipt.recipients.filter(
|
|
889
|
+
(pkh, index, array) => index === array.indexOf(pkh),
|
|
890
|
+
),
|
|
891
|
+
)}`,
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
if (receipt?.fees)
|
|
895
|
+
console.info(` > Network fee: ${colors.yellow(receipt.fees.toString(2))}`);
|
|
896
|
+
if (receipt?.value)
|
|
897
|
+
console.info(
|
|
898
|
+
` > Value: ${colors.myellow(receipt.value.toString(2))}`,
|
|
899
|
+
);
|
|
900
|
+
if (receipt?.weight)
|
|
901
|
+
console.info(` > Weight: ${colors.mgreen(commas(receipt.weight))}`);
|
|
902
|
+
if (receipt?.witnesses) {
|
|
903
|
+
console.info(` > Witnesses: ${receipt.witnesses}`);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
export async function traceTransaction(transmitter, options) {
|
|
908
|
+
const color = options?.color || ((x) => `\x1b[30;45m${x}\x1b[0m`);
|
|
909
|
+
let receipt = await transmitter.signTransaction(options, options?.reload);
|
|
910
|
+
if (options?.verbose) {
|
|
911
|
+
console.info(`\n${gray(JSON.stringify(receipt.tx, txJsonReplacer))}`);
|
|
912
|
+
}
|
|
913
|
+
if (options?.headline) {
|
|
914
|
+
console.info(`\n ${color(` ${options.headline} `)}\n`);
|
|
915
|
+
}
|
|
916
|
+
traceTransactionReceipt(receipt);
|
|
917
|
+
if (!options?.force) {
|
|
918
|
+
// prompt user confirmation
|
|
919
|
+
console.info();
|
|
920
|
+
const answer = await require("inquirer").createPromptModule()([
|
|
921
|
+
{
|
|
922
|
+
message: "Send transaction?",
|
|
923
|
+
type: "confirm",
|
|
924
|
+
name: "continue",
|
|
925
|
+
default: false,
|
|
926
|
+
},
|
|
927
|
+
]);
|
|
928
|
+
if (!answer.continue) {
|
|
929
|
+
return receipt;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
try {
|
|
933
|
+
console.info();
|
|
934
|
+
receipt = await transmitter.sendTransaction();
|
|
935
|
+
if (options?.await || options?.confirmations !== undefined) {
|
|
936
|
+
receipt = await transmitter.confirmTransaction(receipt.hash, {
|
|
937
|
+
confirmations: options?.confirmations || 0,
|
|
938
|
+
onCheckpoint: traceTransactionOnCheckpoint,
|
|
939
|
+
onStatusChange: traceTransactionOnStatusChange,
|
|
940
|
+
});
|
|
941
|
+
} else {
|
|
942
|
+
const data = {
|
|
943
|
+
status: receipt?.status,
|
|
944
|
+
timestamp: receipt?.timestamp || Math.floor(Date.now() / 1000),
|
|
945
|
+
};
|
|
946
|
+
console.info(data);
|
|
947
|
+
}
|
|
948
|
+
} catch (err) {
|
|
949
|
+
if (err?.inFlight && err.inFlight) {
|
|
950
|
+
console.info(
|
|
951
|
+
`\n${colors.gray(JSON.stringify(err.inFligt?.message, txReceiptJsonReplacer))}`,
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
throw err;
|
|
955
|
+
}
|
|
956
|
+
return receipt;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
export function unescapeSlashes(str) {
|
|
960
|
+
// add another escaped slash if the string ends with an odd
|
|
961
|
+
// number of escaped slashes which will crash JSON.parse
|
|
962
|
+
let parsedStr = str.replace(/(^|[^\\])(\\\\)*\\$/, "$&\\");
|
|
963
|
+
|
|
964
|
+
// escape unescaped double quotes to prevent error with
|
|
965
|
+
// added double quotes in json string
|
|
966
|
+
parsedStr = parsedStr.replace(/(^|[^\\])((\\\\)*")/g, "$1\\$2");
|
|
967
|
+
|
|
968
|
+
try {
|
|
969
|
+
parsedStr = JSON.parse(`"${parsedStr}"`);
|
|
970
|
+
} catch (_e) {
|
|
971
|
+
return str;
|
|
972
|
+
}
|
|
973
|
+
return parsedStr;
|
|
974
|
+
}
|