Added TypeScript stage one - replaced js files and fixed syntax errors.
Stage two will be strongly typing things etc.
To compile the js before running:
install typescript if you haven't already - in HiddenWallet.GUI folder run:
npm install -g typescript
then run:
tsc
that generates the .js files the app needs.
MODIFY
HiddenWallet.Gui/HiddenWallet.GUI.njsproj
HiddenWallet.Gui/HiddenWallet.GUI.njsproj
<ProjectGuid>aa83ae28-4fd1-4064-b256-634091a8d738</ProjectGuid>
<ProjectHome>
</ProjectHome>
- <StartupFile>main.js</StartupFile>
+ <StartupFile>
+ </StartupFile>
<StartWebBrowser>False</StartWebBrowser>
<SearchPath>
</SearchPath>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
- <Compile Include="app\js\broadcast-window.js">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="app\js\cleanup.js" />
- <Compile Include="app\js\decryption-phase.js" />
- <Compile Include="app\js\default.js">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="app\js\hw-client.js" />
- <Compile Include="app\js\settings.js" />
- <Compile Include="app\js\status.js" />
- <Compile Include="app\js\wallet-phase.js" />
- <Compile Include="main.js" />
<Content Include="app\assets\TumbleBit.png" />
<Content Include="app\css\default.css">
<SubType>Code</SubType>
<Content Include="build\icon.ico" />
<Content Include="index.html" />
<Content Include="package.json" />
+ <Content Include="tsconfig.json" />
</ItemGroup>
<ItemGroup>
<Folder Include="app\" />
<Folder Include="app\assets\" />
<Folder Include="build\" />
</ItemGroup>
+ <ItemGroup>
+ <TypeScriptCompile Include="app\js\broadcast-window.ts" />
+ <TypeScriptCompile Include="app\js\cleanup.ts" />
+ <TypeScriptCompile Include="app\js\decryption-phase.ts" />
+ <TypeScriptCompile Include="app\js\default.ts" />
+ <TypeScriptCompile Include="app\js\hw-client.ts" />
+ <TypeScriptCompile Include="app\js\settings.ts" />
+ <TypeScriptCompile Include="app\js\status.ts" />
+ <TypeScriptCompile Include="app\js\wallet-phase.ts" />
+ <TypeScriptCompile Include="main.ts" />
+ </ItemGroup>
<!-- Do not delete the following Import Project. While this appears to do nothing it is a marker for setting TypeScript properties before our import that depends on them. -->
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" Condition="False" />
<Import Project="$(VSToolsPath)\Node.js Tools\Microsoft.NodejsTools.targets" />

RENAME
HiddenWallet.Gui/app/js/broadcast-window.js
HiddenWallet.Gui/app/js/broadcast-window.ts
@@ -28,11 +28,17 @@ require('electron').ipcRenderer.on('broadcast-response', (event, response) => {
document.getElementById("transaction").innerText = response.Transaction + "\n HEX: " + hex;
});
+class BroadcastTransaction {
+ hex: any;
+ quickSend: boolean;
+}
+
function broadcastTransaction() {
document.getElementsByClassName("container").item(0).setAttribute("style", "pointer-events:none;");
document.getElementById("broadcast-button").innerHTML = '<span class="glyphicon glyphicon-refresh spinning"></span> Broadcasting...';
- let obj = new Object();
+ // MJH CHECK THIS WORKS - you changed Object() to BroadcastTransaction()
+ let obj = new BroadcastTransaction();
obj.hex = hex;
obj.quickSend = false;
httpPostWalletAsync("send-transaction", obj, function (json) {

RENAME
HiddenWallet.Gui/app/js/cleanup.js
HiddenWallet.Gui/app/js/cleanup.ts
@@ -7,21 +7,21 @@ exports.Cleanup = function Cleanup(callback) {
// attach user callback to the process event emitter
// if no callback, it will still exit gracefully on Ctrl-C
callback = callback || noOp;
- process.on('cleanup', callback);
- // do app specific cleaning before exiting
- process.on('exit', function () {
+ (process as NodeJS.EventEmitter).on('cleanup', callback);
+
+ (process as NodeJS.EventEmitter).on('exit', function () {
process.emit('cleanup');
});
// catch ctrl+c event and exit normally
- process.on('SIGINT', function () {
+ (process as NodeJS.EventEmitter).on('SIGINT', function () {
console.log('Ctrl-C...');
process.exit(2);
});
//catch uncaught exceptions, trace, then exit normally
- process.on('uncaughtException', function (e) {
+ (process as NodeJS.EventEmitter).on('uncaughtException', function (e) {
console.log('Uncaught Exception...');
console.log(e.stack);
process.exit(99);

RENAME
HiddenWallet.Gui/app/js/decryption-phase.js
HiddenWallet.Gui/app/js/decryption-phase.ts
@@ -37,27 +37,27 @@ function decryptionPhaseShow(menuItem = "") {
}
}
else if (menuItem === "decrypt") {
- document.getElementById("menu").innerHTML = document.getElementById("decryption-phase-menu-frame").contentWindow.document.getElementById("decrypt-active").innerHTML;
+ document.getElementById("menu").innerHTML = (<HTMLIFrameElement>document.getElementById("decryption-phase-menu-frame")).contentWindow.document.getElementById("decrypt-active").innerHTML;
if (walletExists === true) {
- document.getElementById("content").innerHTML = document.getElementById("decryption-phase-content-frame").contentWindow.document.getElementById("decrypt-content").innerHTML;
+ document.getElementById("content").innerHTML = (<HTMLIFrameElement>document.getElementById("decryption-phase-content-frame")).contentWindow.document.getElementById("decrypt-content").innerHTML;
}
else {
document.getElementById("content").innerHTML = '<div class="alert alert-warning" role="alert"><strong>No wallet found!</strong> Generate or recover your wallet before decrypting it!</div>';
}
}
else if (menuItem === "generate") {
- document.getElementById("menu").innerHTML = document.getElementById("decryption-phase-menu-frame").contentWindow.document.getElementById("generate-active").innerHTML;
+ document.getElementById("menu").innerHTML = (<HTMLIFrameElement>document.getElementById("decryption-phase-menu-frame")).contentWindow.document.getElementById("generate-active").innerHTML;
if (walletExists === false) {
- document.getElementById("content").innerHTML = document.getElementById("decryption-phase-content-frame").contentWindow.document.getElementById("generate-content").innerHTML;
+ document.getElementById("content").innerHTML = (<HTMLIFrameElement>document.getElementById("decryption-phase-content-frame")).contentWindow.document.getElementById("generate-content").innerHTML;
}
else {
document.getElementById("content").innerHTML = '<div class="alert alert-warning" role="alert"><strong>Wallet already exists!</strong> If you wish to continue with this operation you first need to delete or rename your wallet file!</div>';
}
}
else if (menuItem === "recover") {
- document.getElementById("menu").innerHTML = document.getElementById("decryption-phase-menu-frame").contentWindow.document.getElementById("recover-active").innerHTML;
+ document.getElementById("menu").innerHTML = (<HTMLIFrameElement>document.getElementById("decryption-phase-menu-frame")).contentWindow.document.getElementById("recover-active").innerHTML;
if (walletExists === false) {
- document.getElementById("content").innerHTML = document.getElementById("decryption-phase-content-frame").contentWindow.document.getElementById("recover-content").innerHTML;
+ document.getElementById("content").innerHTML = (<HTMLIFrameElement>document.getElementById("decryption-phase-content-frame")).contentWindow.document.getElementById("recover-content").innerHTML;
}
else {
document.getElementById("content").innerHTML = '<div class="alert alert-warning" role="alert"><strong>Wallet already exists!</strong> If you wish to continue with this operation you first need to delete or rename your wallet file!</div>';
@@ -65,13 +65,17 @@ function decryptionPhaseShow(menuItem = "") {
}
}
+class GenerateWallet {
+ password: string;
+}
+
function generateWallet() {
- let password = document.getElementById("inputPassword").value;
- if (password !== document.getElementById("confirmPassword").value) {
+ let password = (<HTMLInputElement>document.getElementById("inputPassword")).value;
+ if (password !== (<HTMLInputElement>document.getElementById("confirmPassword")).value) {
alert("Could not generate wallet, details:\n\nPassword confirmation does not match the password");
}
else {
- let obj = new Object();
+ let obj = new GenerateWallet();
obj.password = password;
document.getElementsByClassName("container").item(0).setAttribute("style", "pointer-events:none;");
@@ -82,9 +86,9 @@ function generateWallet() {
document.getElementById("generate-wallet-button").innerHTML = "Generate";
}
else {
- document.getElementById("decryption-phase-content-frame").contentWindow.document.getElementById("mnemonic-words").innerHTML = json.Mnemonic;
- document.getElementById("decryption-phase-content-frame").contentWindow.document.getElementById("wallet-creation-time").innerHTML = json.CreationTime.substr(0, 10);
- document.getElementById("content").innerHTML = document.getElementById("decryption-phase-content-frame").contentWindow.document.getElementById("wallet-generated-content").innerHTML;
+ (<HTMLIFrameElement>document.getElementById("decryption-phase-content-frame")).contentWindow.document.getElementById("mnemonic-words").innerHTML = json.Mnemonic;
+ (<HTMLIFrameElement>document.getElementById("decryption-phase-content-frame")).contentWindow.document.getElementById("wallet-creation-time").innerHTML = json.CreationTime.substr(0, 10);
+ document.getElementById("content").innerHTML = (<HTMLIFrameElement>document.getElementById("decryption-phase-content-frame")).contentWindow.document.getElementById("wallet-generated-content").innerHTML;
document.getElementById("menu").hidden = true;
}
document.getElementsByClassName("container").item(0).setAttribute("style", "pointer-events:all;");
@@ -92,10 +96,16 @@ function generateWallet() {
}
}
+class RecoverWallet {
+ password: string;
+ mnemonic: string;
+ creationTime: string;
+}
+
function recoverWallet() {
- let password = document.getElementById("inputPassword").value;
- let mnemonic = document.getElementById("inputMnemonic").value.trim();
- let syncFrom = document.getElementById("inputSyncFrom").value.trim();
+ let password = (<HTMLInputElement>document.getElementById("inputPassword")).value;
+ let mnemonic = (<HTMLInputElement>document.getElementById("inputMnemonic")).value.trim();
+ let syncFrom = (<HTMLInputElement>document.getElementById("inputSyncFrom")).value.trim();
if (mnemonic === "") {
alert("Could not recover wallet, details:\n\nMnemonic is required");
@@ -110,7 +120,7 @@ function recoverWallet() {
alert("Could not recover wallet, details:\n\nWrong 'Syncronize transactions from' date format. Format must be like: 2017-01-01");
}
else {
- let obj = new Object();
+ let obj = new RecoverWallet();
obj.password = password;
obj.mnemonic = mnemonic;
obj.creationTime = syncFrom;
@@ -131,10 +141,14 @@ function recoverWallet() {
}
}
+class DecryptWallet {
+ password: string;
+}
+
function decryptWallet() {
- let password = document.getElementById("inputPassword").value;
+ let password = (<HTMLInputElement>document.getElementById("inputPassword")).value;
- let obj = new Object();
+ let obj = new DecryptWallet();
obj.password = password;
document.getElementsByClassName("container").item(0).setAttribute("style", "pointer-events:none;");

RENAME
HiddenWallet.Gui/app/js/default.js
HiddenWallet.Gui/app/js/default.ts
@@ -64,9 +64,7 @@ const CopyMenu = Menu.buildFromTemplate([{
document.body.addEventListener('contextmenu', (e) => {
e.preventDefault();
e.stopPropagation();
-
- let node = e.target;
-
+ let node:any = e.target;
while (node) {
if (node.nodeName.match(/^(input|textarea)$/i) || node.isContentEditable) {
EditMenu.popup(remote.getCurrentWindow());
@@ -76,13 +74,14 @@ document.body.addEventListener('contextmenu', (e) => {
CopyMenu.popup(remote.getCurrentWindow());
break;
}
- node = node.parentNode;
}
});
// Close the dropdown menu if the user clicks outside of it
window.onclick = function (event) {
- if (!event.target.matches('.dropbtn')) {
+ var eventTarget: any;
+ eventTarget = event.target;
+ if (!eventTarget.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;

RENAME
HiddenWallet.Gui/app/js/hw-client.js
HiddenWallet.Gui/app/js/hw-client.ts
RENAME
HiddenWallet.Gui/app/js/settings.js
HiddenWallet.Gui/app/js/settings.ts
RENAME
HiddenWallet.Gui/app/js/status.js
HiddenWallet.Gui/app/js/status.ts
@@ -50,7 +50,7 @@ function periodicUpdate() {
}
let blocksLeft = "-";
if (trackingHeight !== 0) {
- blocksLeft = headerHeight - trackingHeight;
+ blocksLeft = (headerHeight - trackingHeight).toString();
}
blocksLeftToSync = blocksLeft;
@@ -109,12 +109,14 @@ function updateDecryptButton(ts) {
}
}
if (ts.toUpperCase() === "EstabilishingCircuit".toUpperCase()) {
- document.getElementById("decrypt-wallet-button").innerText = "Waiting for Tor...";
- document.getElementById("decrypt-wallet-button").setAttribute("disabled");
+ var element = <HTMLInputElement>document.getElementById("decrypt-wallet-button");
+ element.innerText = "Waiting for Tor...";
+ element.disabled = true;
}
if (ts.toUpperCase() === "NotStarted".toUpperCase()) {
- document.getElementById("decrypt-wallet-button").innerText = "Waiting for Tor...";
- document.getElementById("decrypt-wallet-button").setAttribute("disabled");
+ var element = <HTMLInputElement>document.getElementById("decrypt-wallet-button");
+ element.innerText = "Waiting for Tor...";
+ element.disabled = true;
}
}
catch (err) {

RENAME
HiddenWallet.Gui/app/js/wallet-phase.js
HiddenWallet.Gui/app/js/wallet-phase.ts
@@ -3,7 +3,7 @@ function walletPhaseShow(tabItem = "") {
if (tabItem === "alice") {
document.getElementById("content").setAttribute("style", "max-height: 320px");
- document.getElementById("tabs").innerHTML = document.getElementById("wallet-phase-tabs-frame").contentWindow.document.getElementById("alice-active").outerHTML;
+ document.getElementById("tabs").innerHTML = (<HTMLIFrameElement>document.getElementById("wallet-phase-tabs-frame")).contentWindow.document.getElementById("alice-active").outerHTML;
storage.set('lastAccount', { lastAccount: 'alice' }, function (error) {
if (error) throw error;
@@ -15,7 +15,7 @@ function walletPhaseShow(tabItem = "") {
}
else if (tabItem === "bob") {
document.getElementById("content").setAttribute("style", "max-height: 320px");
- document.getElementById("tabs").innerHTML = document.getElementById("wallet-phase-tabs-frame").contentWindow.document.getElementById("bob-active").outerHTML;
+ document.getElementById("tabs").innerHTML = (<HTMLIFrameElement>document.getElementById("wallet-phase-tabs-frame")).contentWindow.document.getElementById("bob-active").outerHTML;
storage.set('lastAccount', { lastAccount: 'bob' }, function (error) {
if (error) throw error;
});
@@ -36,15 +36,15 @@ function walletPhaseShow(tabItem = "") {
function walletShow(menuItem) {
if (menuItem === 'receive') {
- document.getElementById("menu").innerHTML = document.getElementById("wallet-menu-frame").contentWindow.document.getElementById("receive-active").outerHTML;
+ document.getElementById("menu").innerHTML = (<HTMLIFrameElement>document.getElementById("wallet-menu-frame")).contentWindow.document.getElementById("receive-active").outerHTML;
}
else if (menuItem === 'send') {
writeHint('Would you consider feeding the developer with some pizza? 186n7me3QKajQZJnUsVsezVhVrSwyFCCZ');
- document.getElementById("menu").innerHTML = document.getElementById("wallet-menu-frame").contentWindow.document.getElementById("send-active").outerHTML;
- document.getElementById("content").innerHTML = document.getElementById("wallet-content-frame").contentWindow.document.getElementById("send-content").outerHTML;
+ document.getElementById("menu").innerHTML = (<HTMLIFrameElement>document.getElementById("wallet-menu-frame")).contentWindow.document.getElementById("send-active").outerHTML;
+ document.getElementById("content").innerHTML = (<HTMLIFrameElement>document.getElementById("wallet-content-frame")).contentWindow.document.getElementById("send-content").outerHTML;
}
else if (menuItem === 'history') {
- document.getElementById("menu").innerHTML = document.getElementById("wallet-menu-frame").contentWindow.document.getElementById("history-active").outerHTML;
+ document.getElementById("menu").innerHTML = (<HTMLIFrameElement>document.getElementById("wallet-menu-frame")).contentWindow.document.getElementById("history-active").outerHTML;
writeHint('HiddenWallet? Easy Peasy Lemon Squeezey!');
}
@@ -66,8 +66,9 @@ function updateWalletContent() {
if (menu.childElementCount > 0) {
let menuId = menu.firstElementChild.id;
if (menuId === "receive-active") {
- document.getElementById("content").innerHTML = document.getElementById("wallet-content-frame").contentWindow.document.getElementById("receive-content").outerHTML;
+ document.getElementById("content").innerHTML = (<HTMLIFrameElement>document.getElementById("wallet-content-frame")).contentWindow.document.getElementById("receive-content").outerHTML;
let resp = httpGetWallet("receive/alice");
+ let i:number = 0
for (i = 0; i < 6; i++) {
let node = document.createElement("li");
node.setAttribute("class", "list-group-item");
@@ -78,8 +79,9 @@ function updateWalletContent() {
document.getElementById("extpubkey").innerText = resp.ExtPubKey;
}
else if (menuId === "history-active") {
- document.getElementById("content").innerHTML = document.getElementById("wallet-content-frame").contentWindow.document.getElementById("history-content").outerHTML;
+ document.getElementById("content").innerHTML = (<HTMLIFrameElement>document.getElementById("wallet-content-frame")).contentWindow.document.getElementById("history-content").outerHTML;
let resp = httpGetWallet("history/alice");
+ let i: number = 0
for (i = 0; i < resp.History.length; i++) {
let trNode = document.createElement("tr");
let tdNodeHeight = document.createElement("td");
@@ -106,8 +108,9 @@ function updateWalletContent() {
if (menu.childElementCount > 0) {
let menuId = menu.firstElementChild.id;
if (menuId === "receive-active") {
- document.getElementById("content").innerHTML = document.getElementById("wallet-content-frame").contentWindow.document.getElementById("receive-content").outerHTML;
+ document.getElementById("content").innerHTML = (<HTMLIFrameElement>document.getElementById("wallet-content-frame")).contentWindow.document.getElementById("receive-content").outerHTML;
let resp = httpGetWallet("receive/bob");
+ let i: number = 0
for (i = 0; i < 6; i++) {
let node = document.createElement("li");
node.setAttribute("class", "list-group-item");
@@ -118,8 +121,9 @@ function updateWalletContent() {
document.getElementById("extpubkey").innerText = resp.ExtPubKey;
}
else if (menuId === "history-active") {
- document.getElementById("content").innerHTML = document.getElementById("wallet-content-frame").contentWindow.document.getElementById("history-content").outerHTML;
+ document.getElementById("content").innerHTML = (<HTMLIFrameElement>document.getElementById("wallet-content-frame")).contentWindow.document.getElementById("history-content").outerHTML;
let resp = httpGetWallet("history/bob");
+ let i: number = 0
for (i = 0; i < resp.History.length; i++) {
let trNode = document.createElement("tr");
let tdNodeHeight = document.createElement("td");
@@ -140,21 +144,28 @@ function updateWalletContent() {
}
function setAmountToAll() {
- document.getElementById("amount-to-send").value = "all";
+ (<HTMLInputElement>document.getElementById("amount-to-send")).value = "all";
+}
+
+class Transaction {
+ password: string;
+ address: string;
+ amount: string;
+ feeType: string;
}
function buildTransaction() {
- var address = document.getElementById("address-to-send").value;
- var amount = document.getElementById("amount-to-send").value;
- var fastFeeChecked = document.getElementById("fast-fee-radio").checked;
- var slowFeeChecked = document.getElementById("slow-fee-radio").checked;
- var password = document.getElementById("send-password").value;
+ var address = (<HTMLInputElement>document.getElementById("address-to-send")).value;
+ var amount = (<HTMLInputElement>document.getElementById("amount-to-send")).value;
+ var fastFeeChecked = (<HTMLInputElement>document.getElementById("fast-fee-radio")).checked;
+ var slowFeeChecked = (<HTMLInputElement>document.getElementById("slow-fee-radio")).checked;
+ var password = (<HTMLInputElement>document.getElementById("send-password")).value;
if (!address) {
alert("Couldn't build the transaciton: Wrong address!");
return;
}
- if (!amount || amount <= 0) {
+ if (!amount || Number(amount) <= 0) {
alert("Couldn't build the transaciton: Wrong amount!");
return;
}
@@ -173,7 +184,7 @@ function buildTransaction() {
if (fastFeeChecked) feeType = "high";
if (slowFeeChecked) feeType = "low";
- let obj = new Object();
+ let obj = new Transaction();
obj.password = password;
obj.address = address;
obj.amount = amount;

ADD
HiddenWallet.Gui/tsconfig.json
+{
+ "compilerOptions": {
+ "noImplicitAny": false,
+ "module": "commonjs",
+ "noEmitOnError": true,
+ "removeComments": true,
+ "sourceMap": false,
+ "target": "es5"
+ },
+ "exclude": [
+ "node_modules"
+ ]
+}

Added TypeScript stage one - replaced js files and fixed syntax errors.
Stage two will be strongly typing things etc.
To compile the js before running:
install typescript if you haven't already - in HiddenWallet.GUI folder run:
npm install -g typescript

then run:
tsc
that generates the .js files the app needs.