Skip to content

Commit

Permalink
feat: add context to App
Browse files Browse the repository at this point in the history
  • Loading branch information
Jblew committed Dec 12, 2018
1 parent 1b3d6f7 commit c929f14
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 62 deletions.
23 changes: 23 additions & 0 deletions src/Context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Log } from "./log";

export class Context {
public stdout: NodeJS.WritableStream;
public stderr: NodeJS.WritableStream;
public stdin: NodeJS.ReadableStream;
public log: (msg: string) => void;
public error: (msg?: string, error?: any) => void;
public debug: (msg: string) => void;
public info: (msg: string) => void;
public exception: (exception: Error, level?: string) => void;

public constructor() {
this.stdout = process.stdout;
this.stdin = process.stdin;
this.stderr = process.stderr;
this.log = console.log;
this.error = console.error;
this.debug = Log.log().debug;
this.info = Log.log().info;
this.exception = (exception: Error, level?: string) => Log.log().exception(level || Log.level.error, exception);
}
}
26 changes: 16 additions & 10 deletions src/actions/DaemonAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ import ow from "ow";
import { ConfigLoader, ConfigLoadedFromFile } from "../config/Config";
import { Wise, DirectBlockchainApi, SteemOperationNumber, SingleDaemon } from "steem-wise-core";
import { StaticConfig } from "../config/StaticConfig";
import { Context } from "../Context";


export class DaemonAction {
public static doAction(config: ConfigLoadedFromFile, sinceBlockNum: undefined | number): Promise<string> {
private context: Context;
public constructor(context: Context) {
this.context = context;
}

public doAction(config: ConfigLoadedFromFile, sinceBlockNum: undefined | number): Promise<string> {
const lastBlockFile = config.syncedBlockNumFile ? (path.dirname(config.configFilePath) + "/" + config.syncedBlockNumFile) : "";

let api: DirectBlockchainApi;
Expand Down Expand Up @@ -39,20 +45,20 @@ export class DaemonAction {
}
})
.then((since: SteemOperationNumber) => {
console.log("Synchronization starting at: " + since);
this.context.log("Synchronization starting at: " + since);

delegatorWise.startDaemon(since, (error: Error | undefined, event: SingleDaemon.Event) => {
if (error) {
console.error(error);
this.context.exception(error);
}

if (event.type === SingleDaemon.EventType.EndBlockProcessing) {
try {
fs.writeFileSync(lastBlockFile, "" + event.blockNum, { flag: "w+" });
console.log("Processed block " + event.blockNum);
this.context.log("Processed block " + event.blockNum);
}
catch (error) {
console.error(error);
this.context.error(error);
}
}
else if (event.type === SingleDaemon.EventType.StartBlockProcessing) {
Expand All @@ -62,15 +68,15 @@ export class DaemonAction {

}
else if (event.type === SingleDaemon.EventType.VoteorderPassed) {
console.log("[Synchronization] (voter=" + event.voter + ") " + event.message);
console.log(JSON.stringify(event.voteorder, undefined, 2));
this.context.log("[Synchronization] (voter=" + event.voter + ") " + event.message);
this.context.log(JSON.stringify(event.voteorder, undefined, 2));
}
else if (event.type === SingleDaemon.EventType.VoteorderRejected) {
console.log("[Synchronization] (voter=" + event.voter + ") " + event.message);
console.log(JSON.stringify(event.voteorder, undefined, 2));
this.context.log("[Synchronization] (voter=" + event.voter + ") " + event.message);
this.context.log(JSON.stringify(event.voteorder, undefined, 2));
}
else if (event) {
console.log("[Synchronization] " + event.message);
this.context.log("[Synchronization] " + event.message);
}
});

Expand Down
20 changes: 16 additions & 4 deletions src/actions/DownloadRulesAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ import { ConfigLoader, Config, ConfigLoadedFromFile } from "../config/Config";
import { Wise, DirectBlockchainApi, SetRulesForVoter, SteemOperationNumber, SetRules, EffectuatedSetRules } from "steem-wise-core";
import { StaticConfig } from "../config/StaticConfig";
import { PrioritizedFileObjectLoader } from "../util/PrioritizedFileObjectLoader";
import { Context } from "../Context";


export class DownloadRulesAction {
public static doAction(config: ConfigLoadedFromFile, file: string, options: any): Promise<string> {
private context: Context;
public constructor(context: Context) {
this.context = context;
}

public doAction(config: ConfigLoadedFromFile, file: string, options: any): Promise<string> {
let format: "yml" | "json" = "yml";
if (options.format) format = "yml";
if (options.format) format = options.format;

const override: boolean = !!options.override;

Expand All @@ -30,7 +36,7 @@ export class DownloadRulesAction {
}
})
.then((account: string) => {
console.log("Downloading rules set by @" + account + "...");
this.context.log("Downloading rules set by @" + account + "...");
return DownloadRulesAction.downloadRules(account, config);
})
.then((result: EffectuatedSetRules []): Promise<string> => {
Expand All @@ -39,7 +45,13 @@ export class DownloadRulesAction {
return esr;
});

const outStr = yaml.safeDump(rulesWithoutMoment);
let outStr: string;
if (format === "yml") {
outStr = yaml.safeDump(rulesWithoutMoment);
}
else {
outStr = JSON.stringify(rulesWithoutMoment, undefined, 2);
}

if (options.stdout) {
return Promise.resolve(outStr + "\n");
Expand Down
50 changes: 29 additions & 21 deletions src/actions/InitAction.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import * as fs from "fs";
import * as prompt from "prompt";
import * as path from "path";
import * as _ from "lodash";
import * as prompt from "prompt";
import * as yaml from "js-yaml";

import { Wise, DirectBlockchainApi, SendVoteorder, SteemOperationNumber } from "steem-wise-core";

import { d } from "../util/util";
import { Log } from "../log";
import { Config } from "../config/Config";
import { StaticConfig } from "../config/StaticConfig";
import { DefaultRules } from "../config/DefaultRules";
import { Context } from "../Context";

export class InitAction {
public static async doAction(options: any, wisePath_: string): Promise<string> {
private context: Context;
public constructor(context: Context) {
this.context = context;
}

public async doAction(options: any, wisePath_: string): Promise<string> {
let wisePath: string = ".";
if (options.global) wisePath = StaticConfig.DEFAULT_GLOBAL_PATH;
if (wisePath_) wisePath = wisePath_;
Expand Down Expand Up @@ -66,17 +73,18 @@ export class InitAction {
hidden: true,
type: "string",
pattern: /^[0-9A-Za-z-]+$/,
ask: function() {
ask: () => {
if (savePostingKey !== undefined) return savePostingKey;
else return prompt.history("savePostingKey").value.toLowerCase().substr(0, 1) === "y";
}
};

await new Promise((resolve, reject) => {
prompt.start({});
prompt.start({ stdin: this.context.stdin, stdout: this.context.stdout });
prompt.get({
properties: propertiesToAsk
}, (error: Error, result: { username: string, savePostingKey: string, postingWif: string }) => {
prompt.stop();
if (error) reject(error);
else {
if (!username) username = result.username;
Expand All @@ -88,23 +96,23 @@ export class InitAction {
});

if (sinceBlock === undefined) {
console.log("Fetching HEAD block number...");
sinceBlock = (await new DirectBlockchainApi(Wise.constructDefaultProtocol()).getDynamicGlobalProperties()).head_block_number;
console.log("HEAB block number is " + sinceBlock);
this.context.log("Fetching HEAD block number...");
sinceBlock = d((await new DirectBlockchainApi(Wise.constructDefaultProtocol()).getDynamicGlobalProperties()).head_block_number);
this.context.log("HEAD block number is " + sinceBlock);
}

console.log("--- Your settings ---");
console.log("Account name: " + username);
console.log("Save posting key: " +
this.context.log("--- Your settings ---");
this.context.log("Account name: " + username);
this.context.log("Save posting key: " +
(savePostingKey ? "Yes. Your posting key is saved to config file. You will not be prompted for it"
: "No. You will be asked for your posting key every time it is required")
);
console.log("Daemon will start synchronisation from block " + sinceBlock);
console.log("Wise path: " + path.resolve(wisePath));
console.log("Config path: " + path.resolve(configPath));
console.log("Rules path: " + path.resolve(rulesPath));
console.log("Synced block num file path: " + path.resolve(syncedBlockNumPath));
console.log("");
this.context.log("Daemon will start synchronisation from block " + sinceBlock);
this.context.log("Wise path: " + path.resolve(wisePath));
this.context.log("Config path: " + path.resolve(configPath));
this.context.log("Rules path: " + path.resolve(rulesPath));
this.context.log("Synced block num file path: " + path.resolve(syncedBlockNumPath));
this.context.log("");

if (fs.existsSync(wisePath)) {
if (!fs.lstatSync(wisePath).isDirectory()) throw new Error("Path " + wisePath + " is not a directory");
Expand All @@ -115,12 +123,12 @@ export class InitAction {
}
}
else {
console.log("Creating " + wisePath + ".");
this.context.log("Creating " + wisePath + ".");
fs.mkdirSync(wisePath);
}


console.log("Writing " + configPath + "");
this.context.log("Writing " + configPath + "");
const configObj = _.merge({}, StaticConfig.DEFAULT_CONFIG, {
username: username,
postingWif: (savePostingKey ? postingKey : ""),
Expand All @@ -131,12 +139,12 @@ export class InitAction {
fs.writeFileSync(configPath, yaml.safeDump(configObj));


console.log("Writing " + syncedBlockNumPath + "");
this.context.log("Writing " + syncedBlockNumPath + "");
fs.writeFileSync(syncedBlockNumPath, sinceBlock + "");

console.log("Writing " + rulesPath + "");
this.context.log("Writing " + rulesPath + "");
fs.writeFileSync(rulesPath, yaml.safeDump(DefaultRules.DEFAULT_RULES));
console.log("Done");
this.context.log("Done");

return "Wise successfully set up in '" + wisePath + "'. Now you have to do two more actions to start the daemon: \n"
+ " 1. Run 'wise upload-rules' to publish the rules to the blockchain.\n"
Expand Down
22 changes: 14 additions & 8 deletions src/actions/SendVoteorderAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,24 @@ import { Wise, DirectBlockchainApi, SendVoteorder, SteemOperationNumber } from "
import { Log } from "../log";
import { ConfigLoader, Config } from "../config/Config";
import { PrioritizedFileObjectLoader } from "../util/PrioritizedFileObjectLoader";
import { Context } from "../Context";


export class SendVoteorderAction {
public static doAction(config: Config, voteorderIn: string): Promise<string> {
return SendVoteorderAction.loadVoteorder(config, voteorderIn)
.then(rawVoteorder => SendVoteorderAction.sendVoteorder(config, rawVoteorder))
private context: Context;
public constructor(context: Context) {
this.context = context;
}

public doAction(config: Config, voteorderIn: string): Promise<string> {
return this.loadVoteorder(config, voteorderIn)
.then(rawVoteorder => this.sendVoteorder(config, rawVoteorder))
.then((moment: SteemOperationNumber) => {
return "Voteorder sent: " + moment;
});
}

private static loadVoteorder(config: Config, voteordetIn: string): Promise<object> {
private loadVoteorder(config: Config, voteordetIn: string): Promise<object> {
const voteorderPaths: string [] = [];

if (voteordetIn && voteordetIn.length > 0) {
Expand All @@ -29,7 +35,7 @@ export class SendVoteorderAction {
return Promise.resolve(data); // succes parsing inline json
}
catch (error) {
Log.log().debug("Failed to parse " + voteordetIn + " as inline JSON. Proceeding to loading files. " + voteorderPaths + " will be loaded as file.");
this.context.debug("Failed to parse " + voteordetIn + " as inline JSON. Proceeding to loading files. " + voteorderPaths + " will be loaded as file.");
voteorderPaths.unshift(voteordetIn);
}
}
Expand All @@ -41,20 +47,20 @@ export class SendVoteorderAction {
});
}

private static sendVoteorder(config: Config, rawVoteorder: object): Promise<SteemOperationNumber> {
private sendVoteorder(config: Config, rawVoteorder: object): Promise<SteemOperationNumber> {
return Promise.resolve()
.then(() => ConfigLoader.askForCredentialsIfEmpty(config))
.then(() => {
const voteorder: VoteorderWithDelegator = rawVoteorder as VoteorderWithDelegator;
console.log(JSON.stringify(voteorder));
this.context.log(JSON.stringify(voteorder));
if (!voteorder.delegator || voteorder.delegator.length == 0) throw new Error("You must specify delegator in voteorder JSON");

const api: DirectBlockchainApi = new DirectBlockchainApi(Wise.constructDefaultProtocol(), config.postingWif, { url: config.steemApi });
if (config.disableSend) api.setSendEnabled(false);
const wise = new Wise(config.username, api);

return wise.sendVoteorder(voteorder.delegator, voteorder, (msg: string, proggress: number) => {
console.log("[voteorder sending][" + Math.floor(proggress * 100) + "%]: " + msg);
this.context.log("[voteorder sending][" + Math.floor(proggress * 100) + "%]: " + msg);
});
});
}
Expand Down
20 changes: 13 additions & 7 deletions src/actions/UploadRulesAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,25 @@ import { ConfigLoader, Config, ConfigLoadedFromFile } from "../config/Config";
import { Wise, DirectBlockchainApi, SetRulesForVoter, SteemOperationNumber } from "steem-wise-core";
import { StaticConfig } from "../config/StaticConfig";
import { PrioritizedFileObjectLoader } from "../util/PrioritizedFileObjectLoader";
import { Context } from "../Context";


export class UploadRulesAction {
public static doAction(config: ConfigLoadedFromFile, rulesIn: string): Promise<string> {
return UploadRulesAction.loadRules(config, rulesIn)
.then((rawRulesets: object []) => UploadRulesAction.syncRules(config, rawRulesets))
private context: Context;
public constructor(context: Context) {
this.context = context;
}

public doAction(config: ConfigLoadedFromFile, rulesIn: string): Promise<string> {
return this.loadRules(config, rulesIn)
.then((rawRulesets: object []) => this.syncRules(config, rawRulesets))
.then((result: SteemOperationNumber | true) => {
if (result === true) return "Rules are up to date";
else return "Rules updated: " + result;
});
}

private static loadRules(config: ConfigLoadedFromFile, rulesIn: string): Promise<object []> {
private loadRules(config: ConfigLoadedFromFile, rulesIn: string): Promise<object []> {
let rulesPaths: string [];
if (config.defaultRulesPath && config.defaultRulesPath.length > 0) {
rulesPaths = [ path.dirname(config.configFilePath) + "/" + config.defaultRulesPath ];
Expand All @@ -36,7 +42,7 @@ export class UploadRulesAction {
return Promise.resolve(data); // succes parsing inline json
}
catch (error) {
Log.log().debug("Failed to parse " + rulesIn + " as inline JSON. Proceeding to loading files. Adding " + rulesIn + " as top-priority file.");
this.context.debug("Failed to parse " + rulesIn + " as inline JSON. Proceeding to loading files. Adding " + rulesIn + " as top-priority file.");
rulesPaths.unshift(rulesIn);
}
}
Expand All @@ -49,7 +55,7 @@ export class UploadRulesAction {
});
}

private static syncRules(config: Config, rawRulesets: object []): Promise<SteemOperationNumber | true> {
private syncRules(config: Config, rawRulesets: object []): Promise<SteemOperationNumber | true> {
return Promise.resolve()
.then(() => ConfigLoader.askForCredentialsIfEmpty(config))
.then(config => {
Expand All @@ -65,7 +71,7 @@ export class UploadRulesAction {
const delegatorWise = new Wise(config.username, api);

return delegatorWise.uploadAllRulesets(newRules, (msg: string, proggress: number) => {
console.log("[syncing a rule][" + Math.floor(proggress * 100) + "%]: " + msg);
this.context.log("[syncing a rule][" + Math.floor(proggress * 100) + "%]: " + msg);
});
});
}
Expand Down
Loading

0 comments on commit c929f14

Please sign in to comment.