@strkfarm/sdk 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js ADDED
@@ -0,0 +1,636 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/cli.ts
27
+ var import_commander = require("commander");
28
+ var import_inquirer = __toESM(require("inquirer"));
29
+
30
+ // src/utils/store.ts
31
+ var import_fs = __toESM(require("fs"));
32
+ var import_starknet5 = require("starknet");
33
+ var crypto2 = __toESM(require("crypto"));
34
+
35
+ // src/utils/encrypt.ts
36
+ var crypto = __toESM(require("crypto"));
37
+ var PasswordJsonCryptoUtil = class {
38
+ constructor() {
39
+ this.algorithm = "aes-256-gcm";
40
+ this.keyLength = 32;
41
+ // 256 bits
42
+ this.saltLength = 16;
43
+ // 128 bits
44
+ this.ivLength = 12;
45
+ // 96 bits for GCM
46
+ this.tagLength = 16;
47
+ // 128 bits
48
+ this.pbkdf2Iterations = 1e5;
49
+ }
50
+ // Number of iterations for PBKDF2
51
+ deriveKey(password, salt) {
52
+ return crypto.pbkdf2Sync(password, salt, this.pbkdf2Iterations, this.keyLength, "sha256");
53
+ }
54
+ encrypt(data, password) {
55
+ const jsonString = JSON.stringify(data);
56
+ const salt = crypto.randomBytes(this.saltLength);
57
+ const iv = crypto.randomBytes(this.ivLength);
58
+ const key = this.deriveKey(password, salt);
59
+ const cipher = crypto.createCipheriv(this.algorithm, key, iv, { authTagLength: this.tagLength });
60
+ let encrypted = cipher.update(jsonString, "utf8", "hex");
61
+ encrypted += cipher.final("hex");
62
+ const tag = cipher.getAuthTag();
63
+ return Buffer.concat([salt, iv, tag, Buffer.from(encrypted, "hex")]).toString("base64");
64
+ }
65
+ decrypt(encryptedData, password) {
66
+ const data = Buffer.from(encryptedData, "base64");
67
+ const salt = data.subarray(0, this.saltLength);
68
+ const iv = data.subarray(this.saltLength, this.saltLength + this.ivLength);
69
+ const tag = data.subarray(this.saltLength + this.ivLength, this.saltLength + this.ivLength + this.tagLength);
70
+ const encrypted = data.subarray(this.saltLength + this.ivLength + this.tagLength);
71
+ const key = this.deriveKey(password, salt);
72
+ const decipher = crypto.createDecipheriv(this.algorithm, key, iv, { authTagLength: this.tagLength });
73
+ decipher.setAuthTag(tag);
74
+ try {
75
+ let decrypted = decipher.update(encrypted.toString("hex"), "hex", "utf8");
76
+ decrypted += decipher.final("utf8");
77
+ return JSON.parse(decrypted);
78
+ } catch (error) {
79
+ throw new Error("Decryption failed. This could be due to an incorrect password or corrupted data.");
80
+ }
81
+ }
82
+ };
83
+
84
+ // src/modules/pricer.ts
85
+ var import_axios = __toESM(require("axios"));
86
+
87
+ // src/data/tokens.json
88
+ var tokens_default = [
89
+ {
90
+ name: "Ether",
91
+ symbol: "ETH",
92
+ address: "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
93
+ decimals: 18,
94
+ pricerKey: "ETH-USDT"
95
+ },
96
+ {
97
+ name: "USD Coin",
98
+ symbol: "USDC",
99
+ address: "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8",
100
+ decimals: 6,
101
+ pricerKey: "USDC-USDT"
102
+ },
103
+ {
104
+ name: "Wrapped BTC",
105
+ symbol: "WBTC",
106
+ address: "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac",
107
+ decimals: 8,
108
+ pricerKey: "WBTC-USDT"
109
+ },
110
+ {
111
+ name: "Tether USD",
112
+ symbol: "USDT",
113
+ address: "0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8",
114
+ decimals: 6,
115
+ pricerKey: "USDT-USDT"
116
+ },
117
+ {
118
+ name: "Dai Stablecoin",
119
+ symbol: "DAIv0",
120
+ address: "",
121
+ decimals: 18,
122
+ pricerKey: "DAI-USDT"
123
+ },
124
+ {
125
+ name: "Starknet Wrapped Staked Ether",
126
+ symbol: "wstETH",
127
+ address: "0x042b8f0484674ca266ac5d08e4ac6a3fe65bd3129795def2dca5c34ecc5f96d2",
128
+ decimals: 18,
129
+ pricerKey: "wstETH-USDT"
130
+ },
131
+ {
132
+ name: "Starknet Token",
133
+ symbol: "STRK",
134
+ address: "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
135
+ decimals: 18,
136
+ pricerKey: "STRK-USDT"
137
+ },
138
+ {
139
+ name: "zkLend Token",
140
+ symbol: "ZEND",
141
+ address: "",
142
+ decimals: 18,
143
+ pricerKey: "ZEND-USDT"
144
+ },
145
+ {
146
+ name: "Dai Stablecoin",
147
+ symbol: "DAI",
148
+ address: "",
149
+ decimals: 18,
150
+ pricerKey: "DAI-USDT"
151
+ },
152
+ {
153
+ name: "Ekubo Protocol",
154
+ symbol: "EKUBO",
155
+ address: "",
156
+ decimals: 18,
157
+ pricerKey: "DAI-USDT"
158
+ }
159
+ ];
160
+
161
+ // src/global.ts
162
+ var logger = {
163
+ ...console,
164
+ verbose(message) {
165
+ console.log(`[VERBOSE] ${message}`);
166
+ }
167
+ };
168
+ var FatalError = class extends Error {
169
+ constructor(message, err) {
170
+ super(message);
171
+ logger.error(message);
172
+ if (err)
173
+ logger.error(err.message);
174
+ this.name = "FatalError";
175
+ }
176
+ };
177
+ var Global = class {
178
+ static fatalError(message, err) {
179
+ logger.error(message);
180
+ console.error(message, err);
181
+ if (err)
182
+ console.error(err);
183
+ process.exit(1);
184
+ }
185
+ static httpError(url, err, message) {
186
+ logger.error(`${url}: ${message}`);
187
+ console.error(err);
188
+ }
189
+ static async getTokens() {
190
+ return tokens_default;
191
+ }
192
+ static assert(condition, message) {
193
+ if (!condition) {
194
+ throw new FatalError(message);
195
+ }
196
+ }
197
+ };
198
+
199
+ // src/modules/pragma.ts
200
+ var import_starknet = require("starknet");
201
+
202
+ // src/modules/zkLend.ts
203
+ var import_axios2 = __toESM(require("axios"));
204
+
205
+ // src/dataTypes/bignumber.ts
206
+ var import_bignumber = __toESM(require("bignumber.js"));
207
+ var Web3Number = class _Web3Number extends import_bignumber.default {
208
+ constructor(value, decimals) {
209
+ super(value);
210
+ this.decimals = decimals;
211
+ }
212
+ static fromWei(weiNumber, decimals) {
213
+ const bn = new _Web3Number(weiNumber, decimals).dividedBy(10 ** decimals);
214
+ return new _Web3Number(bn.toString(), decimals);
215
+ }
216
+ toWei() {
217
+ return this.mul(10 ** this.decimals).toFixed(0);
218
+ }
219
+ multipliedBy(value) {
220
+ return new _Web3Number(this.mul(value).toString(), this.decimals);
221
+ }
222
+ dividedBy(value) {
223
+ return new _Web3Number(this.div(value).toString(), this.decimals);
224
+ }
225
+ plus(value) {
226
+ return new _Web3Number(this.add(value).toString(), this.decimals);
227
+ }
228
+ minus(n, base) {
229
+ return new _Web3Number(super.minus(n, base).toString(), this.decimals);
230
+ }
231
+ toString(base) {
232
+ return super.toString(base);
233
+ }
234
+ // [customInspectSymbol](depth: any, inspectOptions: any, inspect: any) {
235
+ // return this.toString();
236
+ // }
237
+ };
238
+ import_bignumber.default.config({ DECIMAL_PLACES: 18 });
239
+ Web3Number.config({ DECIMAL_PLACES: 18 });
240
+
241
+ // src/interfaces/lending.ts
242
+ var ILending = class {
243
+ constructor(config, metadata) {
244
+ this.tokens = [];
245
+ this.initialised = false;
246
+ this.metadata = metadata;
247
+ this.config = config;
248
+ this.init();
249
+ }
250
+ /** Wait for initialisation */
251
+ waitForInitilisation() {
252
+ return new Promise((resolve, reject) => {
253
+ const interval = setInterval(() => {
254
+ logger.verbose(`Waiting for ${this.metadata.name} to initialise`);
255
+ if (this.initialised) {
256
+ logger.verbose(`${this.metadata.name} initialised`);
257
+ clearInterval(interval);
258
+ resolve();
259
+ }
260
+ }, 1e3);
261
+ });
262
+ }
263
+ };
264
+
265
+ // src/modules/zkLend.ts
266
+ var _ZkLend = class _ZkLend extends ILending {
267
+ constructor(config, pricer) {
268
+ super(config, {
269
+ name: "zkLend",
270
+ logo: "https://app.zklend.com/favicon.ico"
271
+ });
272
+ this.POSITION_URL = "https://app.zklend.com/api/users/{{USER_ADDR}}/all";
273
+ this.pricer = pricer;
274
+ }
275
+ async init() {
276
+ try {
277
+ logger.verbose(`Initialising ${this.metadata.name}`);
278
+ const result = await import_axios2.default.get(_ZkLend.POOLS_URL);
279
+ const data = result.data;
280
+ const savedTokens = await Global.getTokens();
281
+ data.forEach((pool) => {
282
+ let collareralFactor = new Web3Number(0, 0);
283
+ if (pool.collateral_factor) {
284
+ collareralFactor = Web3Number.fromWei(pool.collateral_factor.value, pool.collateral_factor.decimals);
285
+ }
286
+ const savedTokenInfo = savedTokens.find((t) => t.symbol == pool.token.symbol);
287
+ const token = {
288
+ name: pool.token.name,
289
+ symbol: pool.token.symbol,
290
+ address: savedTokenInfo?.address || "",
291
+ decimals: pool.token.decimals,
292
+ borrowFactor: Web3Number.fromWei(pool.borrow_factor.value, pool.borrow_factor.decimals),
293
+ collareralFactor
294
+ };
295
+ this.tokens.push(token);
296
+ });
297
+ logger.info(`Initialised ${this.metadata.name} with ${this.tokens.length} tokens`);
298
+ this.initialised = true;
299
+ } catch (error) {
300
+ return Global.httpError(_ZkLend.POOLS_URL, error);
301
+ }
302
+ }
303
+ /**
304
+ * @description Get the health factor of the user for given lending and debt tokens
305
+ * @param lending_tokens
306
+ * @param debt_tokens
307
+ * @param user
308
+ * @returns hf (e.g. returns 1.5 for 150% health factor)
309
+ */
310
+ async get_health_factor_tokenwise(lending_tokens, debt_tokens, user) {
311
+ const positions = await this.getPositions(user);
312
+ logger.verbose(`${this.metadata.name}:: Positions: ${JSON.stringify(positions)}`);
313
+ let effectiveDebt = new Web3Number(0, 6);
314
+ positions.filter((pos) => {
315
+ return debt_tokens.find((t) => t.symbol === pos.tokenSymbol);
316
+ }).forEach((pos) => {
317
+ const token = this.tokens.find((t) => t.symbol === pos.tokenSymbol);
318
+ if (!token) {
319
+ throw new FatalError(`Token ${pos.tokenName} not found in ${this.metadata.name}`);
320
+ }
321
+ effectiveDebt = effectiveDebt.plus(pos.debtUSD.dividedBy(token.borrowFactor.toFixed(6)).toString());
322
+ });
323
+ logger.verbose(`${this.metadata.name}:: Effective debt: ${effectiveDebt}`);
324
+ if (effectiveDebt.isZero()) {
325
+ return Infinity;
326
+ }
327
+ let effectiveCollateral = new Web3Number(0, 6);
328
+ positions.filter((pos) => {
329
+ const exp1 = lending_tokens.find((t) => t.symbol === pos.tokenSymbol);
330
+ const exp2 = pos.marginType === "shared" /* SHARED */;
331
+ return exp1 && exp2;
332
+ }).forEach((pos) => {
333
+ const token = this.tokens.find((t) => t.symbol === pos.tokenSymbol);
334
+ if (!token) {
335
+ throw new FatalError(`Token ${pos.tokenName} not found in ${this.metadata.name}`);
336
+ }
337
+ logger.verbose(`${this.metadata.name}:: Token: ${pos.tokenName}, Collateral factor: ${token.collareralFactor.toFixed(6)}`);
338
+ effectiveCollateral = effectiveCollateral.plus(pos.supplyUSD.multipliedBy(token.collareralFactor.toFixed(6)).toString());
339
+ });
340
+ logger.verbose(`${this.metadata.name}:: Effective collateral: ${effectiveCollateral}`);
341
+ const healthFactor = effectiveCollateral.dividedBy(effectiveDebt.toFixed(6)).toNumber();
342
+ logger.verbose(`${this.metadata.name}:: Health factor: ${healthFactor}`);
343
+ return healthFactor;
344
+ }
345
+ /**
346
+ * @description Get the health factor of the user
347
+ * - Considers all tokens for collateral and debt
348
+ */
349
+ async get_health_factor(user) {
350
+ return this.get_health_factor_tokenwise(this.tokens, this.tokens, user);
351
+ }
352
+ async getPositionsSummary(user) {
353
+ const pos = await this.getPositions(user);
354
+ const collateralUSD = pos.reduce((acc, p) => acc + p.supplyUSD.toNumber(), 0);
355
+ const debtUSD = pos.reduce((acc, p) => acc + p.debtUSD.toNumber(), 0);
356
+ return {
357
+ collateralUSD,
358
+ debtUSD
359
+ };
360
+ }
361
+ /**
362
+ * @description Get the token-wise collateral and debt positions of the user
363
+ * @param user Contract address of the user
364
+ * @returns Promise<ILendingPosition[]>
365
+ */
366
+ async getPositions(user) {
367
+ const url = this.POSITION_URL.replace("{{USER_ADDR}}", user.address);
368
+ const result = await import_axios2.default.get(url);
369
+ const data = result.data;
370
+ const lendingPosition = [];
371
+ logger.verbose(`${this.metadata.name}:: Positions: ${JSON.stringify(data)}`);
372
+ for (let i = 0; i < data.pools.length; i++) {
373
+ const pool = data.pools[i];
374
+ const token = this.tokens.find((t) => {
375
+ return t.symbol === pool.token_symbol;
376
+ });
377
+ if (!token) {
378
+ throw new FatalError(`Token ${pool.token_symbol} not found in ${this.metadata.name}`);
379
+ }
380
+ const debtAmount = Web3Number.fromWei(pool.data.debt_amount, token.decimals);
381
+ const supplyAmount = Web3Number.fromWei(pool.data.supply_amount, token.decimals);
382
+ const price = (await this.pricer.getPrice(token.symbol)).price;
383
+ lendingPosition.push({
384
+ tokenName: token.name,
385
+ tokenSymbol: token.symbol,
386
+ marginType: pool.data.is_collateral ? "shared" /* SHARED */ : "none" /* NONE */,
387
+ debtAmount,
388
+ debtUSD: debtAmount.multipliedBy(price.toFixed(6)),
389
+ supplyAmount,
390
+ supplyUSD: supplyAmount.multipliedBy(price.toFixed(6))
391
+ });
392
+ }
393
+ ;
394
+ return lendingPosition;
395
+ }
396
+ };
397
+ _ZkLend.POOLS_URL = "https://app.zklend.com/api/pools";
398
+ var ZkLend = _ZkLend;
399
+
400
+ // src/interfaces/common.ts
401
+ var import_starknet2 = require("starknet");
402
+
403
+ // src/dataTypes/address.ts
404
+ var import_starknet3 = require("starknet");
405
+
406
+ // src/strategies/autoCompounderStrk.ts
407
+ var import_starknet4 = require("starknet");
408
+
409
+ // src/notifs/telegram.ts
410
+ var import_node_telegram_bot_api = __toESM(require("node-telegram-bot-api"));
411
+
412
+ // src/node/pricer-redis.ts
413
+ var import_redis = require("redis");
414
+
415
+ // src/utils/store.ts
416
+ function getDefaultStoreConfig(network) {
417
+ if (!process.env.HOME) {
418
+ throw new Error("StoreConfig: HOME environment variable not found");
419
+ }
420
+ return {
421
+ SECRET_FILE_FOLDER: `${process.env.HOME}/.starknet-store`,
422
+ NETWORK: network,
423
+ ACCOUNTS_FILE_NAME: "accounts.json",
424
+ PASSWORD: crypto2.randomBytes(16).toString("hex")
425
+ };
426
+ }
427
+ var Store = class _Store {
428
+ constructor(config, storeConfig) {
429
+ this.encryptor = new PasswordJsonCryptoUtil();
430
+ this.config = config;
431
+ const defaultStoreConfig = getDefaultStoreConfig(config.network);
432
+ if (!storeConfig.PASSWORD) {
433
+ _Store.logPassword(defaultStoreConfig.PASSWORD);
434
+ }
435
+ this.storeConfig = {
436
+ ...defaultStoreConfig,
437
+ ...storeConfig
438
+ };
439
+ _Store.ensureFolder(this.storeConfig.SECRET_FILE_FOLDER);
440
+ }
441
+ static logPassword(password) {
442
+ logger.warn(`\u26A0\uFE0F=========================================\u26A0\uFE0F`);
443
+ logger.warn(`Generated a random password for store`);
444
+ logger.warn(`\u26A0\uFE0F Password: ${password}`);
445
+ logger.warn(`This not stored anywhere, please you backup this password for future use`);
446
+ logger.warn(`\u26A0\uFE0F=========================================\u26A0\uFE0F`);
447
+ }
448
+ getAccount(accountKey) {
449
+ const accounts = this.loadAccounts();
450
+ logger.verbose(`nAccounts loaded for network: ${Object.keys(accounts).length}`);
451
+ const data = accounts[accountKey];
452
+ if (!data) {
453
+ throw new Error(`Account not found: ${accountKey}`);
454
+ }
455
+ logger.verbose(`Account loaded: ${accountKey} from network: ${this.config.network}`);
456
+ logger.verbose(`Address: ${data.address}`);
457
+ return new import_starknet5.Account(this.config.provider, data.address, data.pk);
458
+ }
459
+ addAccount(accountKey, address, pk) {
460
+ const allAccounts = this.getAllAccounts();
461
+ if (!allAccounts[this.config.network]) {
462
+ allAccounts[this.config.network] = {};
463
+ }
464
+ allAccounts[this.config.network][accountKey] = {
465
+ address,
466
+ pk
467
+ };
468
+ const encryptedData = this.encryptor.encrypt(allAccounts, this.storeConfig.PASSWORD);
469
+ (0, import_fs.writeFileSync)(this.getAccountFilePath(), encryptedData);
470
+ logger.verbose(`Account added: ${accountKey} to network: ${this.config.network}`);
471
+ }
472
+ getAccountFilePath() {
473
+ const path = `${this.storeConfig.SECRET_FILE_FOLDER}/${this.storeConfig.ACCOUNTS_FILE_NAME}`;
474
+ logger.verbose(`Path: ${path}`);
475
+ return path;
476
+ }
477
+ getAllAccounts() {
478
+ const PATH = this.getAccountFilePath();
479
+ if (!import_fs.default.existsSync(PATH)) {
480
+ logger.verbose(`Accounts: files doesnt exist`);
481
+ return {};
482
+ }
483
+ let encryptedData = (0, import_fs.readFileSync)(PATH, {
484
+ encoding: "utf-8"
485
+ });
486
+ let data = this.encryptor.decrypt(encryptedData, this.storeConfig.PASSWORD);
487
+ return data;
488
+ }
489
+ /**
490
+ * @description Load all accounts of the network
491
+ * @returns NetworkAccounts
492
+ */
493
+ loadAccounts() {
494
+ const allData = this.getAllAccounts();
495
+ logger.verbose(`Accounts loaded for network: ${this.config.network}`);
496
+ if (!allData[this.config.network]) {
497
+ allData[this.config.network] = {};
498
+ }
499
+ return allData[this.config.network];
500
+ }
501
+ /**
502
+ * @description List all accountKeys of the network
503
+ * @returns string[]
504
+ */
505
+ listAccounts() {
506
+ return Object.keys(this.loadAccounts());
507
+ }
508
+ static ensureFolder(folder) {
509
+ if (!import_fs.default.existsSync(folder)) {
510
+ import_fs.default.mkdirSync(folder, { recursive: true });
511
+ }
512
+ if (!import_fs.default.existsSync(`${folder}`)) {
513
+ throw new Error(`Store folder not found: ${folder}`);
514
+ }
515
+ }
516
+ };
517
+
518
+ // src/cli.ts
519
+ var import_chalk = __toESM(require("chalk"));
520
+ var import_starknet6 = require("starknet");
521
+ var program = new import_commander.Command();
522
+ var getConfig = (network) => {
523
+ return {
524
+ provider: new import_starknet6.RpcProvider({
525
+ nodeUrl: "https://starknet-mainnet.public.blastapi.io"
526
+ }),
527
+ network,
528
+ stage: "production"
529
+ };
530
+ };
531
+ async function createStore() {
532
+ console.log(import_chalk.default.blue.bold("Welcome to the Account Secure project for Starknet!"));
533
+ const networkAnswers = await import_inquirer.default.prompt([
534
+ {
535
+ type: "list",
536
+ name: "network",
537
+ message: import_chalk.default.yellow("What is the network?"),
538
+ choices: ["mainnet", "sepolia", "devnet"]
539
+ }
540
+ ]);
541
+ const network = networkAnswers.network;
542
+ const defaultStoreConfig = getDefaultStoreConfig(network);
543
+ const storeConfigAnswers = await import_inquirer.default.prompt([
544
+ {
545
+ type: "input",
546
+ name: "secrets_folder",
547
+ message: import_chalk.default.yellow(`What is your secrets folder? (${defaultStoreConfig.SECRET_FILE_FOLDER})`),
548
+ default: defaultStoreConfig.SECRET_FILE_FOLDER,
549
+ validate: (input) => true
550
+ },
551
+ {
552
+ type: "input",
553
+ name: "accounts_file",
554
+ message: import_chalk.default.yellow(`What is your accounts file? (${defaultStoreConfig.ACCOUNTS_FILE_NAME})`),
555
+ default: defaultStoreConfig.ACCOUNTS_FILE_NAME,
556
+ validate: (input) => true
557
+ },
558
+ {
559
+ type: "input",
560
+ name: "encryption_password",
561
+ message: import_chalk.default.yellow(`What is your decryption password? (To generate one, press enter)`),
562
+ default: defaultStoreConfig.PASSWORD,
563
+ validate: (input) => true
564
+ }
565
+ ]);
566
+ const config = getConfig(network);
567
+ const secrets_folder = storeConfigAnswers.secrets_folder;
568
+ const accounts_file = storeConfigAnswers.accounts_file;
569
+ const encryption_password = storeConfigAnswers.encryption_password;
570
+ const store = new Store(config, {
571
+ SECRET_FILE_FOLDER: secrets_folder,
572
+ ACCOUNTS_FILE_NAME: accounts_file,
573
+ PASSWORD: storeConfigAnswers.encryption_password,
574
+ NETWORK: network
575
+ });
576
+ if (defaultStoreConfig.PASSWORD === encryption_password) {
577
+ Store.logPassword(encryption_password);
578
+ }
579
+ return store;
580
+ }
581
+ program.version("1.0.0").description("Manage accounts securely on your disk with encryption");
582
+ program.description("Add accounts securely to your disk with encryption").command("add-account").action(async (options) => {
583
+ const store = await createStore();
584
+ const existingAccountKeys = store.listAccounts();
585
+ const accountAnswers = await import_inquirer.default.prompt([
586
+ {
587
+ type: "input",
588
+ name: "account_key",
589
+ message: import_chalk.default.yellow(`Provide a unique account key`),
590
+ validate: (input) => input.length > 0 && !existingAccountKeys.includes(input) || "Please enter a unique account key"
591
+ },
592
+ {
593
+ type: "input",
594
+ name: "address",
595
+ message: import_chalk.default.yellow(`What is your account address?`),
596
+ validate: (input) => input.length > 0 || "Please enter a valid address"
597
+ },
598
+ {
599
+ type: "input",
600
+ name: "pk",
601
+ message: import_chalk.default.yellow(`What is your account private key?`),
602
+ validate: (input) => input.length > 0 || "Please enter a valid pk"
603
+ }
604
+ ]);
605
+ const address = accountAnswers.address;
606
+ const pk = accountAnswers.pk;
607
+ const account_key = accountAnswers.account_key;
608
+ store.addAccount(account_key, address, pk);
609
+ console.log(`${import_chalk.default.blue("Account added:")} ${account_key} to network: ${store.config.network}`);
610
+ });
611
+ program.description("List account names of a network").command("list-accounts").action(async (options) => {
612
+ const store = await createStore();
613
+ const accounts = store.listAccounts();
614
+ console.log(`${import_chalk.default.blue("Account keys:")} ${accounts.join(", ")}`);
615
+ });
616
+ program.description("List account names of a network").command("get-account").action(async (options) => {
617
+ const store = await createStore();
618
+ const existingAccountKeys = store.listAccounts();
619
+ const accountAnswers = await import_inquirer.default.prompt([
620
+ {
621
+ type: "input",
622
+ name: "account_key",
623
+ message: import_chalk.default.yellow(`Provide a unique account key`),
624
+ validate: (input) => input.length > 0 && existingAccountKeys.includes(input) || "Please enter a value account key"
625
+ }
626
+ ]);
627
+ const account = store.getAccount(accountAnswers.account_key);
628
+ console.log(`${import_chalk.default.blue("Account Address:")} ${account.address}`);
629
+ });
630
+ program.action(() => {
631
+ program.help();
632
+ });
633
+ program.parse(process.argv);
634
+ if (!process.argv.slice(2).length) {
635
+ program.outputHelp();
636
+ }