diff --git a/package.json b/package.json index 358ace0..d5e480f 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,9 @@ "jquery-browserify": "*", "crypto-js": "3.1.2-3", "bitcoinjs-lib": "0.2.0", - "openpgp": "0.6.1" + "openpgp": "0.6.1", + "sjcl": "1.0.1", + "sanitizer" : "0.1.2", + "pretty-date" : "0.2.0" } } diff --git a/src/ninki-api.js b/src/ninki-api.js index 953f718..e0966cf 100644 --- a/src/ninki-api.js +++ b/src/ninki-api.js @@ -46,12 +46,10 @@ API.post = function (url, postData, callback) { function lpost(url, postData, callback) { - //https://ninkip2p.com - var sessionToken = $('#API-Token').val(); - + // $.ajax({ - url: "https://localhost:1111" + url, + url: "https://api.ninkip2p.com:443" + url, type: "POST", data: JSON.stringify(postData), contentType: "application/json; charset=utf-8", @@ -59,14 +57,10 @@ function lpost(url, postData, callback) { headers: { 'api-token': sessionToken }, success: function (data) { - data = sanitizer.sanitize(data); - var jdata = JSON.parse(data); - - if (jdata.error) { return callback(true, jdata.message); } @@ -76,6 +70,10 @@ function lpost(url, postData, callback) { return callback(false, JSON.stringify(jdata)); }, fail: function (data, textStatus) { + + data = sanitizer.sanitize(data); + textStatus = sanitizer.sanitize(textStatus); + return callback(true, { textStatus: textStatus, data: data @@ -83,34 +81,36 @@ function lpost(url, postData, callback) { }, error: function (data) { - console.log(data); + if (data.status == 403) { //session has been lost - } - else if (data.status == 401) { - - // if (!window.cordova) { - // if (chrome) { - // if (chrome.runtime) { - // if (chrome.runtime.reload) { - // chrome.runtime.reload() - // } else { - // location.reload(); - // } - // } else { - // location.reload(); - // } - // //return callback(true, data.statusText); - // } else { - // location.reload(); - // } - // } else { - // - // } + } else if (data.status == 401) { + + if (!window.cordova) { + if (chrome) { + if (chrome.runtime) { + if (chrome.runtime.reload) { + chrome.runtime.reload() + } else { + location.reload(); + } + } else { + location.reload(); + } + //return callback(true, data.statusText); + } else { + location.reload(); + } + } else { + + } } else { + + data.responseText = sanitizer.sanitize(data.responseText); + return callback(true, data.responseText); } @@ -316,6 +316,21 @@ API.getUnconfirmedBalance = function (guid, sharedid, callback) { }); } +//function for increased performance on login +API.getAccountData = function (guid, sharedid, callback) { + var postData = { guid: guid, sharedid: sharedid }; + return lpost("/api/1/u/getaccountdata", postData, function (err, dataStr) { + return callback(err, dataStr); + }); +} + +API.getUserData = function (guid, sharedid, callback) { + var postData = { guid: guid, sharedid: sharedid }; + return lpost("/api/1/u/getuserdata", postData, function (err, dataStr) { + return callback(err, dataStr); + }); +} + //gets the username associated with the wallet API.getNickname = function (guid, sharedid, callback) { @@ -345,9 +360,12 @@ API.getUnspentOutputs = function (guid, sharedid, callback) { var postData = { guid: guid, sharedid: sharedid }; return lpost("/api/1/u/getunspentoutputs", postData, function (err, response) { - var data1 = response; - var data2 = JSON.parse(data1); - return callback(err, data2.Message); + if (!err) { + var data = JSON.parse(response); + return callback(err, data.Message); + } else { + return callback(err, response); + } }); } @@ -356,17 +374,25 @@ API.getCoinProfile = function (guid, sharedid, callback) { var postData = { guid: guid, sharedid: sharedid }; return lpost("/api/1/u/getcoinprofile", postData, function (err, response) { - var data = JSON.parse(response); - return callback(err, data); + if (!err) { + var data = JSON.parse(response); + return callback(err, data); + } else { + return callback(err, response); + } }); } -API.getPrice = function (ccy, callback) { +API.getPrice = function (guid, ccy, callback) { - var postData = { ccy: ccy }; - return lpost("/api/1/u/getPrice", postData, function (err, response) { - var data = JSON.parse(response); - return callback(err, data); + var postData = { guid: guid, ccy: ccy }; + return lpost("/api/1/u/getprice", postData, function (err, response) { + if (!err) { + var data = JSON.parse(response); + return callback(err, data); + } else { + return callback(err, response); + } }); } @@ -375,9 +401,12 @@ API.getPendingUserRequests = function (guid, sharedid, callback) { //these are requests made by me to other people var postData = { guid: guid, sharedid: sharedid }; return lpost("/api/1/u/getpendinguserrequests", postData, function (err, data) { - var friends = JSON.parse(data); - - return callback(err, friends); + if (!err) { + var friends = JSON.parse(data); + return callback(err, friends); + } else { + return callback(err, data); + } }); } @@ -385,8 +414,12 @@ API.getFriendRequests = function (guid, sharedid, callback) { var postData = { guid: guid, sharedid: sharedid }; return lpost("/api/1/u/getfriendrequests", postData, function (err, dataStr) { - var jdata = JSON.parse(dataStr); - return callback(err, jdata); + if (!err) { + var jdata = JSON.parse(dataStr); + return callback(err, jdata); + } else { + return callback(err, dataStr); + } }); } @@ -394,25 +427,31 @@ API.getUserPacket = function (guid, sharedid, callback) { var postData = { guid: guid, sharedid: sharedid }; return lpost("/api/1/u/getuserpacket", postData, function (err, dataStr) { - - var jdata = JSON.parse(dataStr); - return callback(err, jdata); + if (!err) { + var jdata = JSON.parse(dataStr); + return callback(err, jdata); + } else { + return callback(err, dataStr); + } }); } API.isNetworkExist = function (guid, sharedid, username, callback) { var postData = { guid: guid, sharedid: sharedid, username: username }; lpost("/api/1/u/doesnetworkexist", postData, function (err, result) { - var exists = JSON.parse(result); - return callback(err, exists); - + if (!err) { + var exists = JSON.parse(result); + return callback(err, exists); + } else { + return callback(err, result); + } }); } API.rejectFriendRequest = function (guid, sharedid, username, callback) { var postData = { guid: guid, sharedid: sharedid, username: username }; - lpost("/api/1/u/rejectfriend", params, function (err, result) { + lpost("/api/1/u/rejectfriend", postData, function (err, result) { return callback(err, result); }); } @@ -423,9 +462,12 @@ API.getTransactionRecords = function (guid, sharedid, callback) { lpost("/api/1/u/gettransactionrecords", postData, function (err, transactions) { - var jtran = JSON.parse(transactions); - - return callback(err, jtran); + if (!err) { + var jtran = JSON.parse(transactions); + return callback(err, jtran); + } else { + return callback(err, transactions); + } }); @@ -437,9 +479,13 @@ API.getInvoiceList = function (guid, sharedid, callback) { lpost("/api/1/u/getinvoicestopay", postData, function (err, invoices) { - var jtran = JSON.parse(invoices); + if (!err) { + var jtran = JSON.parse(invoices); - return callback(err, jtran); + return callback(err, jtran); + } else { + return callback(err, invoices); + } }); @@ -451,9 +497,12 @@ API.getInvoiceByUserList = function (guid, sharedid, callback) { lpost("/api/1/u/getinvoicesbyuser", postData, function (err, invoices) { - var jtran = JSON.parse(invoices); - - return callback(err, jtran); + if (!err) { + var jtran = JSON.parse(invoices); + return callback(err, jtran); + } else { + return callback(err, invoices); + } }); @@ -483,7 +532,7 @@ API.registerDevice = function (guid, deviceName, deviceId, deviceModel, devicePI } API.getDeviceKey = function (guid, devicePIN, regToken, callback) { - var postData = { guid: guid, devicePIN: devicePIN, regToken: regToken}; + var postData = { guid: guid, devicePIN: devicePIN, regToken: regToken }; return lpost("/api/1/u/getdevicekey", postData, function (err, dataStr) { return callback(err, dataStr); }); @@ -516,8 +565,12 @@ API.createDevice = function (guid, sharedid, deviceName, callback) { API.getDevices = function (guid, sharedid, callback) { var postData = { guid: guid, sharedid: sharedid }; return lpost("/api/1/u/getdevices", postData, function (err, dataStr) { - var jdevs = JSON.parse(dataStr); - return callback(err, jdevs); + if (!err) { + var jdevs = JSON.parse(dataStr); + return callback(err, jdevs); + } else { + return callback(err, dataStr); + } }); } diff --git a/src/ninki-engine.js b/src/ninki-engine.js index 6c9258f..e7cba68 100644 --- a/src/ninki-engine.js +++ b/src/ninki-engine.js @@ -31,6 +31,7 @@ function Engine() { this.m_pubKey = ''; this.m_APIToken = ''; this.m_appInitialised = false; + this.m_watchOnly = false; m_this = this; @@ -205,7 +206,7 @@ function Engine() { }; }; - + this.pbkdf2 = pbkdf2; function pbkdf2(password, salt) { var passwordSalt = sjcl.codec.utf8String.toBits(salt); var derivedKey = sjcl.misc.pbkdf2(password, passwordSalt, 1000, 256, hmac); @@ -224,9 +225,90 @@ function Engine() { } + this.getEncHotHash = getEncHotHash; + function getEncHotHash(callback) { + + var isWeb = isBrowser(); + if (isChromeApp()) { + + chrome.storage.local.get("hk" + m_this.m_guid, function (result) { + + if (result["hk" + m_this.m_guid]) { + + var hk = result["hk" + m_this.m_guid]; + + chrome.storage.local.get("hkiv" + m_this.m_guid, function (resultiv) { + + if (resultiv["hkiv" + m_this.m_guid]) { + + var hkiv = resultiv["hkiv" + m_this.m_guid]; + + var data = "{\"enc\":\"" + hk + "\", \"iv\":\"" + hkiv + "\"}"; + return callback(false, data); + } else { + return callback(true, "ErrMissing"); + } + + }); + + } else { + return callback(true, "ErrMissing"); + } + + }); + + } else { + + return callback(true, "ErrInvalid"); + } + + + + } + + + this.restoreHotHash = restoreHotHash; + + function restoreHotHash(hothash, callback) { + + + + //validate against loaded hot public key + var validseed = true; + try { + var bipHot = Bitcoin.HDWallet.fromSeedHex(hothash); + if (m_this.m_walletinfo.hotPub != bipHot.toString()) { + validseed = false; + } + } catch (error) { + + validseed = false; + } + + if (validseed) { + + saveHotHash(hothash, function (err, result) { + + if (!err) { + return callback(false, hothash); + } else { + return callback(err, result); + } + + }); + + } else { + + return callback(true, "ErrSeedInvalid"); + + } + + } + + this.getHotHash = getHotHash; function getHotHash(key, callback) { @@ -507,7 +589,7 @@ function Engine() { } else { - $('#textMessageCreate').html('stretching password...'); + $('#textMessageCreate').text('stretching password...'); setTimeout(function () { @@ -541,7 +623,7 @@ function Engine() { walletInformation.wallet.recPacketIV = recpacket.iv.toString(); //save the wallet to the server - $('#textMessageCreate').html('saving data...'); + $('#textMessageCreate').text('saving data...'); setTimeout(function () { @@ -579,7 +661,8 @@ function Engine() { //TODO add some more param checking //rename this function setTimeout(function () { - $('#textMessageCreate').html('creating account...'); + + $('#textMessageCreate').text('creating account...'); API.getMasterPublicKeyFromUpstreamServer(m_this.m_oguid, function (err, ninkiPubKey, userToken, secret) { if (err) { @@ -604,7 +687,7 @@ function Engine() { var network = "mainnet"; - $('#textMessageCreate').html('getting entropy...'); + $('#textMessageCreate').text('getting entropy...'); setTimeout(function () { //get some random data for the cold key @@ -631,7 +714,7 @@ function Engine() { //var seedtest = bip39.mnemonicToSeed(hotmnem, ''); - $('#textMessageCreate').html('creating cold keys...'); + $('#textMessageCreate').text('creating cold keys...'); setTimeout(function () { @@ -644,7 +727,7 @@ function Engine() { var coldPriv = coldWallet.toString(" "); var coldPub = coldWallet.toString(); - $('#textMessageCreate').html('creating hot keys...'); + $('#textMessageCreate').text('creating hot keys...'); setTimeout(function () { @@ -667,7 +750,7 @@ function Engine() { var hcbkey = Bitcoin.convert.hexToBytes(hckey); var hchkey = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(hcbkey)).toString(); - $('#textMessageCreate').html('creating pgp keys...'); + $('#textMessageCreate').text('creating pgp keys...'); setTimeout(function () { @@ -684,7 +767,7 @@ function Engine() { setTimeout(function () { - $('#textMessageCreate').html('encrypting data...'); + $('#textMessageCreate').text('encrypting data...'); //save the wallet keys and user token in an encrypted packet //AES256 using PBKDF2 on the password and a unique salt @@ -796,35 +879,22 @@ function Engine() { m_this.m_twoFactorOnLogin = true; - getPGPKeys(function (err, result) { - - if (!err) { - getSettings(function (err, result) { + getSettings(function (err, result) { - callback(err, result); + callback(err, result); - }); - } else { - callback(err, result); - } }); + } }); } else { - getPGPKeys(function (err, result) { + getSettings(function (err, result) { - if (!err) { - getSettings(function (err, result) { - - callback(err, result); + callback(err, result); - }); - } else { - callback(err, result); - } }); } @@ -832,10 +902,11 @@ function Engine() { } - this.openWallet2fa = openWallet2fa; - function openWallet2fa(twoFactCode, rememberTwoFactor, callback) { + this.migrateHotKeyFromPacket = migrateHotKeyFromPacket; + function migrateHotKeyFromPacket(twoFactCode, callback) { - API.getWalletFromServer(m_this.m_guid, m_this.m_secret, twoFactCode, rememberTwoFactor, function (err, wallet) { + + API.getWalletFromServer(m_this.m_guid, m_this.m_secret, twoFactCode, false, function (err, wallet) { if (err) { return callback(err, wallet); @@ -847,10 +918,14 @@ function Engine() { return callback(true, "Incorrect password"); } - //if any account still has a hotkey stored in their encrypted packet //then remove it and resave the packet + + // show a notice to the user that their hotkey has been migrated locally + // they should write this down as they will need t to setup their wallet + // on a new PC or if they uninstall the chrome app + if (walletInformation.hotHash != '') { var hotHash = walletInformation.hotHash; @@ -873,6 +948,7 @@ function Engine() { var postData = { twoFactorCode: twoFactCode, guid: m_this.m_guid, sharedid: walletInformation.userToken, accountPacket: packet.toString(), IVA: packet.iv.toString() }; API.post("/api/1/u/migratepacket", postData, function (err, dataStr) { + return callback(false, "ok"); }); @@ -887,6 +963,24 @@ function Engine() { } + }); + + } + + this.openWallet2fa = openWallet2fa; + function openWallet2fa(twoFactCode, rememberTwoFactor, callback) { + + API.getWalletFromServer(m_this.m_guid, m_this.m_secret, twoFactCode, rememberTwoFactor, function (err, wallet) { + + if (err) { + return callback(err, wallet); + } + + try { + var walletInformation = decrypt(wallet.Payload, m_this.m_password, wallet.IV); + } catch (err) { + return callback(true, "Incorrect password"); + } if (m_this.m_migrateBeta12fa) { @@ -928,20 +1022,14 @@ function Engine() { //save secret - getPGPKeys(function (err, result) { + getSettings(function (err, result) { if (!err) { - getSettings(function (err, result) { - if (!err) { - callback(err, wallet); - } else { - callback(err, result); - } - - }); + callback(err, wallet); } else { callback(err, result); } + }); } @@ -954,9 +1042,9 @@ function Engine() { //2. this is the standard login code execution //eventually only this block will be required - walletInformation.hotPriv = ''; - walletInformation.hotHash = ''; - walletInformation.hchkey = ''; + //walletInformation.hotPriv = ''; + //walletInformation.hotHash = ''; + //walletInformation.hchkey = ''; m_this.m_twoFactorOnLogin = wallet.TwoFactorOnLogin; m_this.m_walletinfo = walletInformation; @@ -974,22 +1062,16 @@ function Engine() { //save secret - getPGPKeys(function (err, result) { - + getSettings(function (err, result) { if (!err) { - getSettings(function (err, result) { - if (!err) { - callback(err, wallet); - } else { - callback(err, result); - } - - }); + callback(err, wallet); } else { callback(err, result); } + }); + } }); @@ -1089,26 +1171,20 @@ function Engine() { //alert and remind the user to write down their hotkeys - walletInformation.hotPriv = ''; - walletInformation.hotHash = ''; - walletInformation.hchkey = ''; + //walletInformation.hotPriv = ''; + //walletInformation.hotHash = ''; + //walletInformation.hchkey = ''; m_this.m_twoFactorOnLogin = wallet.TwoFactorOnLogin; m_this.m_walletinfo = walletInformation; m_this.m_sharedid = walletInformation.userToken; - getPGPKeys(function (err, result) { - if (!err) { - getSettings(function (err, result) { + getSettings(function (err, result) { - callback(err, result); + callback(err, result); - }); - } else { - callback(err, result); - } }); @@ -1179,19 +1255,14 @@ function Engine() { m_this.m_walletinfo = walletInformation; m_this.m_sharedid = walletInformation.userToken; - getPGPKeys(function (err, result) { - if (!err) { - getSettings(function (err, result) { + getSettings(function (err, result) { - callback(err, result); + callback(err, result); - }); - } else { - callback(err, result); - } }); + }); }); @@ -1245,52 +1316,56 @@ function Engine() { } - function getSettings(callback) { - //nickname in packet? - getNickname(function (err, nickname) { - m_this.m_nickname = nickname; + function getSettings(callback) { + //nickname in packet? + getUserData(function (err, data) { - getUserProfile(function (err, result) { + if (!err) { - var userProfile = JSON.parse(result); + data = JSON.parse(data); - m_this.m_profileImage = userProfile.ProfileImage; - m_this.m_statusText = userProfile.Status; - m_this.m_invoiceTax = userProfile.Tax; + m_this.m_nickname = data.Nickname; - getFingerPrint(function (err, fingerprint) { - //display the secret on a div + m_this.m_profileImage = data.ProfileImage; + m_this.m_statusText = data.Status; + m_this.m_invoiceTax = data.Tax; - var bip39 = new BIP39(); // 'en' is the default language - var fingermnem = bip39.entropyToMnemonic(fingerprint); - m_this.m_fingerprint = fingermnem; - getAccountSettings(function (err, response) { - if (err) { + //display the secret on a div + var rsaKeyPair = decrypt(data.Payload, m_this.m_password, data.IV); - } else { + var publicKeys = openpgp.key.readArmored(rsaKeyPair.RSAPub); + var privKeys = openpgp.key.readArmored(rsaKeyPair.RSAPriv); - var settingsObject = JSON.parse(response); - m_this.m_settings = settingsObject; - m_this.m_validate = !settingsObject.EmailVerified; - } + m_this.m_privKey = privKeys.keys[0]; + m_this.m_pubKey = publicKeys.keys[0]; - return callback(err, "ok"); + if (m_this.m_privKey.decrypt(m_this.m_sharedid)) { + var bip39 = new BIP39(); // 'en' is the default language + var fingermnem = bip39.entropyToMnemonic(m_this.m_pubKey.primaryKey.fingerprint); - }); + m_this.m_fingerprint = fingermnem; + m_this.m_settings = data.Settings; + m_this.m_validate = !data.Settings.EmailVerified; - }); + return callback(err, "ok"); + } else { + callback(true, 'failed'); + } + } else { - }); + return callback(err, data); + } }); } + function deriveChild(path, hdwallet) { var e = path.split('/'); @@ -1493,23 +1568,26 @@ function Engine() { //setup handles to report back progress var progressel = ''; var messel = ''; + var progresselnum = '' if (sendType == 'friend') { messel = '#textMessageSend'; progressel = '#sendfriendprogstatus'; + progresselnum = '#sendstdprognum'; } if (sendType == 'standard') { messel = '#textMessageSendStd'; progressel = '#sendstdprogstatus'; + progresselnum = '#sendstdprognum'; } if (sendType == 'invoice') { messel = '#textMessageSendInv'; progressel = '#sendinvprogstatus'; + progresselnum = '#sendstdprognum'; } - var minersFee = 10000; //?? amount = Math.round(amount); @@ -1540,313 +1618,365 @@ function Engine() { var pdata = { guid: m_this.m_guid, sharedid: m_this.m_sharedid }; - $(messel).html('Getting unspent outputs...'); + $(messel).text('Getting unspent outputs...'); API.post("/api/1/u/getunspentoutputs", pdata, function (err, outputs) { - var outputs = JSON.parse(outputs); - var outputsToSpend = []; - var amountsToSend = []; - var addressToSend = []; - var userHotPrivKeys = []; - var nodeLevels = []; - var publicKeys = []; - var packet = { addressToSend: addressToSend, amountsToSend: amountsToSend, outputsToSpend: outputsToSpend, userHotPrivKeys: userHotPrivKeys, guid: m_this.m_guid, paths: nodeLevels, publicKeys: publicKeys }; + if (!err) { - //get outputs to spend, calculate change amount minus miners fee + var outputs = JSON.parse(outputs); + var outputsToSpend = []; + var amountsToSend = []; + var addressToSend = []; + var userHotPrivKeys = []; - $(progressel).width('20%'); + var nodeLevels = []; + var publicKeys = []; + var packet = { addressToSend: addressToSend, amountsToSend: amountsToSend, outputsToSpend: outputsToSpend, userHotPrivKeys: userHotPrivKeys, guid: m_this.m_guid, paths: nodeLevels, publicKeys: publicKeys }; - //iterate the unspent outputs and select the first n that equal the amount to spend - //TO DO: do this before doing any key derivation - var amountSoFar = 0; - for (var i = 0; i < outputs.length; i++) { + //get outputs to spend, calculate change amount minus miners fee - var pitem = outputs[i]; - var pout = { transactionId: pitem.TransactionId, outputIndex: pitem.OutputIndex, amount: pitem.Amount, address: pitem.Address } + $(progressel).width('20%'); + if ($(progresselnum)) { + $(progresselnum).text('20%'); + } - nodeLevels.push(pitem.NodeLevel); + //iterate the unspent outputs and select the first n that equal the amount to spend + //TO DO: do this before doing any key derivation + var amountSoFar = 0; + for (var i = 0; i < outputs.length; i++) { - outputsToSpend.push(pout); + var pitem = outputs[i]; + var pout = { transactionId: pitem.TransactionId, outputIndex: pitem.OutputIndex, amount: pitem.Amount, address: pitem.Address } - //derive the private key to use for signing - userHotPrivKeys.push(deriveChild(pitem.NodeLevel, bipHot).priv); + nodeLevels.push(pitem.NodeLevel); - //derive the public keys to use for script generation - //this could be cached on the server as no privacy or hand-off issue that I can see + outputsToSpend.push(pout); - var dbipHotPub = ""; - var dbipColdPub = ""; - var dbipNinkiPub = ""; + //derive the private key to use for signing + userHotPrivKeys.push(deriveChild(pitem.NodeLevel, bipHot).priv); - if (pitem.PK1.length > 0) { + //derive the public keys to use for script generation + //this could be cached on the server as no privacy or hand-off issue that I can see - dbipHotPub = Bitcoin.convert.hexToBytes(pitem.PK1); - dbipColdPub = Bitcoin.convert.hexToBytes(pitem.PK2); - dbipNinkiPub = Bitcoin.convert.hexToBytes(pitem.PK3); + var dbipHotPub = ""; + var dbipColdPub = ""; + var dbipNinkiPub = ""; - } else { + if (pitem.PK1.length > 0) { + + dbipHotPub = Bitcoin.convert.hexToBytes(pitem.PK1); + dbipColdPub = Bitcoin.convert.hexToBytes(pitem.PK2); + dbipNinkiPub = Bitcoin.convert.hexToBytes(pitem.PK3); - dbipHotPub = deriveChild(pitem.NodeLevel, bipHotPub).pub.toBytes(); - dbipColdPub = deriveChild(pitem.NodeLevel, bipCold).pub.toBytes(); - dbipNinkiPub = deriveChild(pitem.NodeLevel, bipNinki).pub.toBytes(); + } else { + + dbipHotPub = deriveChild(pitem.NodeLevel, bipHotPub).pub.toBytes(); + dbipColdPub = deriveChild(pitem.NodeLevel, bipCold).pub.toBytes(); + dbipNinkiPub = deriveChild(pitem.NodeLevel, bipNinki).pub.toBytes(); + + } + + publicKeys.push([dbipHotPub, dbipColdPub, dbipNinkiPub]); + + //add the amount + amountSoFar += pitem.Amount; + + if ((amountSoFar - amount) >= minersFee) { + break; + } } - publicKeys.push([dbipHotPub, dbipColdPub, dbipNinkiPub]); + amountsToSend.push(amount); - //add the amount - amountSoFar += pitem.Amount; + //now create the change + //again move this before the key derivation + var changeAmount = amountSoFar - (amount + minersFee); - if ((amountSoFar - amount) >= minersFee) { - break; + if (changeAmount < 0) { + //this message needs to be handled carefully + //as the wallet will most likely have pending confirmations + //rather than insufficent funds + return callback(true, "ErrInsufficientFunds"); } - } + if (changeAmount > 0) { + amountsToSend.push(changeAmount); + } - amountsToSend.push(amount); + //create a new address for my change to be sent back to me - //now create the change - //again move this before the key derivation - var changeAmount = amountSoFar - (amount + minersFee); + //if we are sending money to a contact or paying an invoice + //we need to derive addresses on their behalf - if (changeAmount < 0) { - //this message needs to be handled carefully - //as the wallet will most likely have pending confirmations - //rather than insufficent funds - return callback(true, "ErrInsufficientFunds"); - } + if (sendType == 'friend' || sendType == 'invoice') { + var params = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: friendUserName, amount: amount }; - if (changeAmount > 0) { - amountsToSend.push(changeAmount); - } + //generate the address for the contact + //this must be done on the client + $(messel).text('Creating address...'); + createAddressForFriend(friendUserName, function (err, address) { - //create a new address for my change to be sent back to me + if (!err) { - //if we are sending money to a contact or paying an invoice - //we need to derive addresses on their behalf + $(progressel).width('40%'); + if ($(progresselnum)) { + $(progresselnum).text('40%'); + } - if (sendType == 'friend' || sendType == 'invoice') { - var params = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: friendUserName, amount: amount }; + addressToSend.push(address); - //generate the address for the contact - //this must be done on the client - $(messel).html('Creating address...'); - createAddressForFriend(friendUserName, function (err, address) { + //create the change address, this must be done on the client + $(messel).text('Creating change address...'); - if (!err) { + createAddress('m/0/1', changeAmount, function (err, changeaddress) { - $(progressel).width('40%'); - addressToSend.push(address); + if (!err) { + $(progressel).width('60%'); + if ($(progresselnum)) { + $(progresselnum).text('60%'); + } - //create the change address, this must be done on the client - $(messel).html('Creating change address...'); - createAddress('m/0/1', changeAmount, function (err, changeaddress) { + if (changeAmount > 0) { + addressToSend.push(changeaddress); + } + //now get the transaction data + $(messel).text('Creating transaction...'); + aGetTransactionData(packet, function (err, hashesForSigning, rawTransaction) { - if (!err) { - $(progressel).width('60%'); - if (changeAmount > 0) { - addressToSend.push(changeaddress); - } - //now get the transaction data - $(messel).html('Creating transaction...'); - aGetTransactionData(packet, function (err, hashesForSigning, rawTransaction) { + $(progressel).width('80%'); + if ($(progresselnum)) { + $(progresselnum).text('80%'); + } - $(progressel).width('80%'); - var jsonSend = { guid: m_this.m_guid, hashesForSigning: hashesForSigning, rawTransaction: rawTransaction, pathsToSignWith: nodeLevels } - var jsonp1 = { guid: m_this.m_guid, jsonPacket: JSON.stringify(jsonSend), sharedid: m_this.m_sharedid, twoFactorCode: twoFactorCode, userName: friendUserName }; - $(messel).html('Counter-signing transaction...'); - //send the transaction to the service for countersigning and broadcast to the network + var jsonSend = { guid: m_this.m_guid, hashesForSigning: hashesForSigning, rawTransaction: rawTransaction, pathsToSignWith: nodeLevels } + var jsonp1 = { guid: m_this.m_guid, jsonPacket: JSON.stringify(jsonSend), sharedid: m_this.m_sharedid, twoFactorCode: twoFactorCode, userName: friendUserName }; + $(messel).text('Counter-signing transaction...'); + //send the transaction to the service for countersigning and broadcast to the network - //requires 2 factor authentication - API.post("/api/1/u/sendtransaction", jsonp1, function (err, result) { + //requires 2 factor authentication - if (!err) { - $(progressel).width('100%'); - $(messel).html('Transaction broadcast...'); - //error handling? - - //we have a transaction id so lets make a note of the transaction in the database - var params = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: friendUserName, transactionid: result, address: address, amount: amount }; - API.post("/api/1/u/createtransactionrecord", params, function (err, result) { - return callback(err, params.transactionid); - }); - } else { + API.post("/api/1/u/sendtransaction", jsonp1, function (err, result) { - //handle error messages returned from the server - if (result == 'ErrSingleTransactionLimit') { + if (!err) { $(progressel).width('100%'); - $(messel).html('Transaction Failed: Single limit exceeded'); - return callback(err, result); - } + if ($(progresselnum)) { + $(progresselnum).text('100%'); + } - if (result == 'ErrDailyTransactionLimit') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Daily limit exceeded'); - return callback(err, result); - } - if (result == 'ErrTransactionsPerDayLimit') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Daily number limit exceeded'); - return callback(err, result); - } + $(messel).text('Transaction broadcast...'); + //error handling? - if (result == 'ErrTransactionsPerHourLimit') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Hourly number limit exceeded'); - return callback(err, result); - } + //we have a transaction id so lets make a note of the transaction in the database + var params = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: friendUserName, transactionid: result, address: address, amount: amount }; + API.post("/api/1/u/createtransactionrecord", params, function (err, result) { + return callback(err, params.transactionid); + }); + } else { - if (result == 'ErrInvalidRequest') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Invalid request'); - return callback(err, result); - } + //handle error messages returned from the server + if (result == 'ErrSingleTransactionLimit') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Single limit exceeded'); + return callback(err, result); + } - if (result == 'ErrLocked') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Account is unavailable'); - return callback(err, result); - } + if (result == 'ErrDailyTransactionLimit') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Daily limit exceeded'); + return callback(err, result); + } + if (result == 'ErrTransactionsPerDayLimit') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Daily number limit exceeded'); + return callback(err, result); + } - if (result == 'ErrBroadcastFailed') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Not accepted'); - return callback(err, result); - } + if (result == 'ErrTransactionsPerHourLimit') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Hourly number limit exceeded'); + return callback(err, result); + } - if (result == "Invalid two factor code") { - $(progressel).width('100%'); - $(messel).html("Invalid two factor code"); - return callback(err, result); - } + if (result == 'ErrInvalidRequest') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Invalid request'); + return callback(err, result); + } - } + if (result == 'ErrLocked') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Account is unavailable'); + return callback(err, result); + } + + + if (result == 'ErrBroadcastFailed') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Not accepted'); + return callback(err, result); + } + + if (result == "Invalid two factor code") { + $(progressel).width('100%'); + $(messel).text("Invalid two factor code"); + return callback(err, result); + } + + } + }); }); - }); - } else { - //create address error - if (changeaddress == 'ErrInvalidRequest') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Invalid request'); - return callback(err, changeaddress); + } else { + //create address error + if (changeaddress == 'ErrInvalidRequest') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Invalid request'); + return callback(err, changeaddress); + } } + }); + } else { + + if (address == 'ErrInvalidRequest') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Invalid request'); + return callback(err, address); } - }); - } else { - if (address == 'ErrInvalidRequest') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Invalid request'); - return callback(err, address); } + }); + } else { - } - }); - } else { + $(messel).text('Creating address...'); - $(messel).html('Creating address...'); + addressToSend.push(addressTo); - addressToSend.push(addressTo); + //create the change address, this must be done on the client + createAddress('m/0/1', changeAmount, function (err, changeaddress) { - //create the change address, this must be done on the client - createAddress('m/0/1', changeAmount, function (err, changeaddress) { + if (!err) { - if (!err) { + $(progressel).width('40%'); - $(progressel).width('40%'); - if (changeAmount > 0) { - addressToSend.push(changeaddress); - } + if ($(progresselnum)) { + $(progresselnum).text('40%'); + } - //now get the transaction - $(messel).html('Creating transaction...'); - aGetTransactionData(packet, function (err, hashesForSigning, rawTransaction) { - $(progressel).width('60%'); - var jsonSend = { guid: m_this.m_guid, hashesForSigning: hashesForSigning, rawTransaction: rawTransaction, pathsToSignWith: nodeLevels } - var jsonp1 = { guid: m_this.m_guid, jsonPacket: JSON.stringify(jsonSend), sharedid: m_this.m_sharedid, twoFactorCode: twoFactorCode, userName: '' }; - $(messel).html('Counter-signing transaction...'); - API.post("/api/1/u/sendtransaction", jsonp1, function (err, result) { + if (changeAmount > 0) { + addressToSend.push(changeaddress); + } - $(progressel).width('80%'); - if (!err) { - $(progressel).width('100%'); - $(messel).html('Transaction broadcast...'); + //now get the transaction + $(messel).text('Creating transaction...'); + aGetTransactionData(packet, function (err, hashesForSigning, rawTransaction) { + $(progressel).width('60%'); + if ($(progresselnum)) { + $(progresselnum).text('60%'); + } - //we have a transaction id so lets make a note of the transaction in the database - var params = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: 'External', transactionid: result, address: addressTo, amount: amount }; - API.post("/api/1/u/createtransactionrecord", params, function (err, result) { - return callback(err, result); - }); - } else { - if (result == 'ErrSingleTransactionLimit') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Single limit exceeded'); - return callback(err, result); - } + var jsonSend = { guid: m_this.m_guid, hashesForSigning: hashesForSigning, rawTransaction: rawTransaction, pathsToSignWith: nodeLevels } + var jsonp1 = { guid: m_this.m_guid, jsonPacket: JSON.stringify(jsonSend), sharedid: m_this.m_sharedid, twoFactorCode: twoFactorCode, userName: '' }; + $(messel).text('Counter-signing transaction...'); + API.post("/api/1/u/sendtransaction", jsonp1, function (err, result) { - if (result == 'ErrDailyTransactionLimit') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Daily limit exceeded'); - return callback(err, result); - } + $(progressel).width('80%'); - if (result == 'ErrTransactionsPerDayLimit') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Daily number limit exceeded'); - return callback(err, result); + if ($(progresselnum)) { + $(progresselnum).text('80%'); } - if (result == 'ErrTransactionsPerHourLimit') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Hourly number limit exceeded'); - return callback(err, result); - } - if (result == 'ErrInvalidRequest') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Invalid request'); - return callback(err, result); - } + if (!err) { - if (result == 'ErrBroadcastFailed') { + if ($(progresselnum)) { + $(progresselnum).text('100%'); + } $(progressel).width('100%'); - $(messel).html('Transaction Failed: Not accepted'); - return callback(err, result); - } + $(messel).text('Transaction broadcast...'); - if (result == "Invalid two factor code") { - $(progressel).width('100%'); - $(messel).html("Invalid two factor code"); - return callback(err, result); - } + //we have a transaction id so lets make a note of the transaction in the database + var params = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: 'External', transactionid: result, address: addressTo, amount: amount }; + API.post("/api/1/u/createtransactionrecord", params, function (err, result) { + return callback(err, result); + }); + } else { + if (result == 'ErrSingleTransactionLimit') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Single limit exceeded'); + return callback(err, result); + } + + if (result == 'ErrDailyTransactionLimit') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Daily limit exceeded'); + return callback(err, result); + } - } + if (result == 'ErrTransactionsPerDayLimit') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Daily number limit exceeded'); + return callback(err, result); + } + + if (result == 'ErrTransactionsPerHourLimit') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Hourly number limit exceeded'); + return callback(err, result); + } + + if (result == 'ErrInvalidRequest') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Invalid request'); + return callback(err, result); + } + + + if (result == 'ErrBroadcastFailed') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Not accepted'); + return callback(err, result); + } + + if (result == "Invalid two factor code") { + $(progressel).width('100%'); + $(messel).text("Invalid two factor code"); + return callback(err, result); + } + + + } + }); }); - }); - } else { + } else { + + //create address error + if (changeaddress == 'ErrInvalidRequest') { + $(progressel).width('100%'); + $(messel).text('Transaction Failed: Invalid request'); + return callback(err, changeaddress); + } - //create address error - if (changeaddress == 'ErrInvalidRequest') { - $(progressel).width('100%'); - $(messel).html('Transaction Failed: Invalid request'); - return callback(err, changeaddress); } + }); + } + + } else { + + return callback(err, outputs); - } - }); } }); @@ -1926,62 +2056,70 @@ function Engine() { API.post("/api/1/u/getfriendpacket", postData, function (err, packet) { - //get the packet from friend containing the public key set to - //be used for address generation and decrypt - - var msg = openpgp.message.readArmored(packet); - var decrypted = openpgp.decryptAndVerifyMessage(m_this.m_privKey, [m_this.m_pubKey], msg); - - var pubkeys = JSON.parse(sanitizer.sanitize(decrypted.text)); - //var pubkeys = decrypt(packet, password, params.oguid); - //only allow address to be created if the packet has been validated - if (pubkeys.validated) { - //get the next leaf on the contacts address space node assigned to this user - API.post("/api/1/u/getnextleafforfriend", postData, function (err, leaf) { - - //derive the public keys - var path = 'm/' + leaf; - - var bipHot = Bitcoin.HDWallet.fromBase58(pubkeys.hotPub); - var bipCold = Bitcoin.HDWallet.fromBase58(pubkeys.coldPub); - var bipNinki = Bitcoin.HDWallet.fromBase58(pubkeys.ninkiPub); - - var hotKey = deriveChild(path, bipHot); - var coldKey = deriveChild(path, bipCold); - var ninkiKey = deriveChild(path, bipNinki); - - //now create the multisig address - var script = [0x52]; - script.push(33); - script = script.concat(hotKey.pub.toBytes()); - script.push(33); - script = script.concat(coldKey.pub.toBytes()); - script.push(33); - script = script.concat(ninkiKey.pub.toBytes()); - script.push(0x53); - script.push(0xae); - var address = multiSig(script); - - //register the address with the server - var postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: username, address: address, leaf: leaf, pk1: hotKey.pub.toString(), pk2: coldKey.pub.toString(), pk3: ninkiKey.pub.toString() }; - API.post("/api/1/u/createaddressforfriend", postData, function (err, result) { + if (!err) { - if (!err) { - return callback(err, address); - } else { - return callback(err, result); - } + //get the packet from friend containing the public key set to + //be used for address generation and decrypt + + var msg = openpgp.message.readArmored(packet); + var decrypted = openpgp.decryptAndVerifyMessage(m_this.m_privKey, [m_this.m_pubKey], msg); + + var pubkeys = JSON.parse(sanitizer.sanitize(decrypted.text)); + //var pubkeys = decrypt(packet, password, params.oguid); + //only allow address to be created if the packet has been validated + if (pubkeys.validated) { + //get the next leaf on the contacts address space node assigned to this user + API.post("/api/1/u/getnextleafforfriend", postData, function (err, leaf) { + + //derive the public keys + var path = 'm/' + leaf; + + var bipHot = Bitcoin.HDWallet.fromBase58(pubkeys.hotPub); + var bipCold = Bitcoin.HDWallet.fromBase58(pubkeys.coldPub); + var bipNinki = Bitcoin.HDWallet.fromBase58(pubkeys.ninkiPub); + + var hotKey = deriveChild(path, bipHot); + var coldKey = deriveChild(path, bipCold); + var ninkiKey = deriveChild(path, bipNinki); + + //now create the multisig address + var script = [0x52]; + script.push(33); + script = script.concat(hotKey.pub.toBytes()); + script.push(33); + script = script.concat(coldKey.pub.toBytes()); + script.push(33); + script = script.concat(ninkiKey.pub.toBytes()); + script.push(0x53); + script.push(0xae); + var address = multiSig(script); + + //register the address with the server + var postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: username, address: address, leaf: leaf, pk1: hotKey.pub.toString(), pk2: coldKey.pub.toString(), pk3: ninkiKey.pub.toString() }; + API.post("/api/1/u/createaddressforfriend", postData, function (err, result) { + + if (!err) { + return callback(err, address); + } else { + return callback(err, result); + } + + }); + + //now update the address to the server }); + } else { - //now update the address to the server + //something very bad has happened + //attempting to derive an address for a non validated contact + return callback(true, "ErrInvalid"); + } - }); } else { - //something very bad has happened - //attempting to derive an address for a non validated contact return callback(true, "ErrInvalid"); + } }); @@ -2067,8 +2205,12 @@ function Engine() { function getUserNetwork(callback) { var postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid }; API.post("/api/1/u/getusernetwork", postData, function (err, data) { - var friends = JSON.parse(data); - return callback(err, friends); + if (!err) { + var friends = JSON.parse(data); + return callback(err, friends); + } else { + return callback(err, data); + } }); } @@ -2079,10 +2221,12 @@ function Engine() { var postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: username }; return API.post("/api/1/u/getfriend", postData, function (err, data) { - - var friend = JSON.parse(data); - - return callback(err, friend); + if (!err) { + var friend = JSON.parse(data); + return callback(err, friend); + } else { + return callback(err, data); + } }); } @@ -2096,7 +2240,7 @@ function Engine() { var postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: username }; if ($(uimessage)) { - $(uimessage).html('Assigning node...'); + $(uimessage).text('Assigning node...'); } API.post("/api/1/u/getnextnodeforfriend", postData, function (err, node) { @@ -2113,31 +2257,31 @@ function Engine() { var hotKey = deriveChild(node, bipHot).toString(); if ($(uimessage)) { - $(uimessage).html('Deriving address.'); + $(uimessage).text('Deriving address.'); } setTimeout(function () { var coldKey = deriveChild(node, bipCold).toString(); if ($(uimessage)) { - $(uimessage).html('Deriving address..'); + $(uimessage).text('Deriving address..'); } setTimeout(function () { var ninkiKey = deriveChild(node, bipNinki).toString(); if ($(uimessage)) { - $(uimessage).html('Deriving address...'); + $(uimessage).text('Deriving address...'); } //get the friends public RSA key var rsaKey = ''; - $(uimessage).html('Get PGP keys...'); + $(uimessage).text('Get PGP keys...'); API.post("/api/1/u/getrsakey", postData, function (err, rsaKey) { var publicKeys = openpgp.key.readArmored(rsaKey); if ($(uimessage)) { - $(uimessage).html('Encrypting data...'); + $(uimessage).text('Encrypting data...'); } var pubKey = publicKeys.keys[0]; @@ -2194,7 +2338,7 @@ function Engine() { var isValid = decrypted.signatures[0].valid; if (isValid) { - + var keys = sanitizer.sanitize(decrypted.text); var key1 = keys.substring(0, 111); @@ -2251,45 +2395,51 @@ function Engine() { //there was no easy way to change this password in the library so i opted to go with a fixed password //instead of a blank one + if (!err) { - var msg = openpgp.message.readArmored(packet); - var decrypted = openpgp.decryptAndVerifyMessage(m_this.m_privKey, [m_this.m_pubKey], msg); + var msg = openpgp.message.readArmored(packet); + var decrypted = openpgp.decryptAndVerifyMessage(m_this.m_privKey, [m_this.m_pubKey], msg); - var isValid = decrypted.signatures[0].valid; - if (isValid) { + var isValid = decrypted.signatures[0].valid; + if (isValid) { - var payload = JSON.parse(sanitizer.sanitize(decrypted.text)); + var payload = JSON.parse(sanitizer.sanitize(decrypted.text)); - var publicKeysUsed = openpgp.key.readArmored(payload.rsaKey); - var pubKeyUsed = publicKeysUsed.keys[0]; + var publicKeysUsed = openpgp.key.readArmored(payload.rsaKey); + var pubKeyUsed = publicKeysUsed.keys[0]; - if (code == pubKeyUsed.primaryKey.fingerprint) { + if (code == pubKeyUsed.primaryKey.fingerprint) { - var reencrypt = { - hotPub: payload.hotPub, - coldPub: payload.coldPub, - ninkiPub: payload.ninkiPub, - rsaKey: payload.rsaKey, - validated: true - }; + var reencrypt = { + hotPub: payload.hotPub, + coldPub: payload.coldPub, + ninkiPub: payload.ninkiPub, + rsaKey: payload.rsaKey, + validated: true + }; - var encryptedPayload = openpgp.signAndEncryptMessage([m_this.m_pubKey], m_this.m_privKey, JSON.stringify(reencrypt)); + var encryptedPayload = openpgp.signAndEncryptMessage([m_this.m_pubKey], m_this.m_privKey, JSON.stringify(reencrypt)); - postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: username, packet: encryptedPayload, validationHash: code }; + postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: username, packet: encryptedPayload, validationHash: code }; - API.post("/api/1/u/updatefriend", postData, function (err, result) { + API.post("/api/1/u/updatefriend", postData, function (err, result) { - return callback(err, result); + return callback(err, result); - }); + }); - return callback(err, true); - } else { - return callback(err, false); + } else { + + return callback(err, false); + + } } + } else { + + return callback(err, result); } @@ -2394,7 +2544,7 @@ function Engine() { var isValid = decrypted.signatures[0].valid; if (isValid) { - + var json = JSON.parse(sanitizer.sanitize(decrypted.text)); //remove any xss data @@ -2420,7 +2570,6 @@ function Engine() { var postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, - twoFactorOnLogin: true, twoFactorCode: twoFactorCode, verifyToken: verifyToken }; @@ -2458,7 +2607,6 @@ function Engine() { var postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, - twoFactorOnLogin: true, twoFactorCode: twoFactorCode, verifyToken: '' }; @@ -2540,7 +2688,7 @@ function Engine() { getHotHash("", function (err, hothash) { $(progbar).width('40%'); - $(progmess).html('Securing password...'); + $(progmess).text('Securing password...'); setTimeout(function () { //if password reset do not pbkdf the password @@ -2549,10 +2697,10 @@ function Engine() { //get the two packets $(progbar).width('40%'); - $(progmess).html('Getting packets...'); + $(progmess).text('Getting packets...'); // $("#chngpwdprogbar").width('50%'); - //$("#chngpwdprogmess").html('Decrypting account packet...'); + //$("#chngpwdprogmess").text('Decrypting account packet...'); //decrypt with the old password var decryptedWithOld = true; var decryptedPayload = ''; @@ -2565,7 +2713,7 @@ function Engine() { if (decryptedWithOld) { $(progbar).width('80%'); - $(progmess).html('Securing new password...'); + $(progmess).text('Securing new password...'); API.getUserPacket(m_this.m_guid, m_this.m_sharedid, function (err, encpacket) { var decryptedUsrWithOld = true; @@ -2587,151 +2735,159 @@ function Engine() { }, function (err, response) { - //decrypt packet - var decryptedVerWithOld = true; - var jpacket = JSON.parse(response); - var veripacket = ''; - try { - veripacket = decryptNp(jpacket.packet, m_this.m_password, jpacket.IV); - } - catch (verror) { - decryptedVerWithOld = false; - } + if (!err) { + //decrypt packet + var decryptedVerWithOld = true; + var jpacket = JSON.parse(response); + var veripacket = ''; + try { + veripacket = decryptNp(jpacket.packet, m_this.m_password, jpacket.IV); + } + catch (verror) { + decryptedVerWithOld = false; + } - if (decryptedVerWithOld) { - setTimeout(function () { + if (decryptedVerWithOld) { + setTimeout(function () { - newpassword = pbkdf2(newpassword, m_this.m_oguid); + newpassword = pbkdf2(newpassword, m_this.m_oguid); - $(progbar).width('80%'); - $(progmess).html('Encrypting account packet...'); - var newpayloadsuccess = true; - var newpayload = ''; - var newusrpayload = ''; - var newveripacket = ''; - var newpasspacket = ''; - var newAIV = ''; - var newUIV = ''; - var newRIV = ''; - var newPIV = '' - try { + $(progbar).width('80%'); + $(progmess).text('Encrypting account packet...'); - newpayload = encrypt(decryptedPayload, newpassword); - newusrpayload = encrypt(rsaKeyPair, newpassword); - newveripacket = encryptNp(veripacket, newpassword); + var newpayloadsuccess = true; + var newpayload = ''; + var newusrpayload = ''; + var newveripacket = ''; + var newpasspacket = ''; + var newAIV = ''; + var newUIV = ''; + var newRIV = ''; + var newPIV = '' + try { - if (decryptedPayload.hckey) { - newpasspacket = encryptNp(newpassword, decryptedPayload.hckey); - } + newpayload = encrypt(decryptedPayload, newpassword); + newusrpayload = encrypt(rsaKeyPair, newpassword); + newveripacket = encryptNp(veripacket, newpassword); + + if (decryptedPayload.hckey) { + newpasspacket = encryptNp(newpassword, decryptedPayload.hckey); + } - newAIV = newpayload.iv.toString(); - newUIV = newusrpayload.iv.toString(); - newRIV = newveripacket.iv.toString(); + newAIV = newpayload.iv.toString(); + newUIV = newusrpayload.iv.toString(); + newRIV = newveripacket.iv.toString(); - if (decryptedPayload.hckey) { - newPIV = newpasspacket.iv.toString(); + if (decryptedPayload.hckey) { + newPIV = newpasspacket.iv.toString(); + } + + } catch (err) { + newpayloadsuccess = false; } - } catch (err) { - newpayloadsuccess = false; - } + if (newpayloadsuccess) { - if (newpayloadsuccess) { + //$("#chngpwdprogbar").width('90%'); + //$("#chngpwdprogmess").text('Encrypting user packet...'); - //$("#chngpwdprogbar").width('90%'); - //$("#chngpwdprogmess").html('Encrypting user packet...'); + //test decryption - then update + var testpayload = ''; + var testnewusrpayload = ''; + var testveripacket = ''; + var testpasspacket = ''; + var testsuccess = true; + try { - //test decryption - then update - var testpayload = ''; - var testnewusrpayload = ''; - var testveripacket = ''; - var testpasspacket = ''; - var testsuccess = true; - try { + testpayload = decrypt(newpayload.toString(), newpassword, newAIV); + testnewusrpayload = decrypt(newusrpayload.toString(), newpassword, newUIV); + testveripacket = decryptNp(newveripacket.toString(), newpassword, newRIV); - testpayload = decrypt(newpayload.toString(), newpassword, newAIV); - testnewusrpayload = decrypt(newusrpayload.toString(), newpassword, newUIV); - testveripacket = decryptNp(newveripacket.toString(), newpassword, newRIV); + if (decryptedPayload.hckey) { + testpasspacket = decryptNp(newpasspacket.toString(), decryptedPayload.hckey, newPIV) + } - if (decryptedPayload.hckey) { - testpasspacket = decryptNp(newpasspacket.toString(), decryptedPayload.hckey, newPIV) + } catch (err) { + testsuccess = false; } - } catch (err) { - testsuccess = false; - } + if (testsuccess) { - if (testsuccess) { + //save to the server + $(progbar).width('95%'); + $(progmess).text('Saving...'); - //save to the server - $(progbar).width('95%'); - $(progmess).html('Saving...'); + //TO DO: + //add in the re-encryption of the verification + //packet - //TO DO: - //add in the re-encryption of the verification - //packet + //if reset password then provide signed message and call reset function - //if reset password then provide signed message and call reset function + //need to add two factor here + //so 1. add two factor + //2. add way to save only the main packet - //need to add two factor here - //so 1. add two factor - //2. add way to save only the main packet + var postData = { twoFactorCode: twoFactorCode, guid: m_this.m_guid, sharedid: m_this.m_sharedid, accountPacket: newpayload.toString(), userPacket: newusrpayload.toString(), verifyPacket: newveripacket.toString(), passPacket: newpasspacket.toString(), IVA: newAIV, IVU: newUIV, IVR: newRIV, PIV: newPIV }; + API.post("/api/1/u/updatepackets", postData, function (err, dataStr) { + if (err) { + callback(true, "Error: Password not changed"); + } else { - var postData = { twoFactorCode: twoFactorCode, guid: m_this.m_guid, sharedid: m_this.m_sharedid, accountPacket: newpayload.toString(), userPacket: newusrpayload.toString(), verifyPacket: newveripacket.toString(), passPacket: newpasspacket.toString(), IVA: newAIV, IVU: newUIV, IVR: newRIV, PIV: newPIV }; - API.post("/api/1/u/updatepackets", postData, function (err, dataStr) { - if (err) { - callback(true, "Error: Password not changed"); - } else { + if (dataStr == "ok") { - if (dataStr == "ok") { + m_this.m_password = newpassword; - m_this.m_password = newpassword; + //if something goes wrong here + //the worst case scenario is the + //user has to reenter their hot key - //if something goes wrong here - //the worst case scenario is the - //user has to reenter their hot key + saveHotHash(hothash, function (err, result) { - saveHotHash(hothash, function (err, result) { + callback(false, ''); - callback(false, ''); + }); - }); + } else { - } else { + callback(true, "Error: Password not changed"); + } - callback(true, "Error: Password not changed"); } + }); + - } - }); + } else { + callback(true, "Error: Password not changed"); + } } else { callback(true, "Error: Password not changed"); } - } else { + }, 500); - callback(true, "Error: Password not changed"); + } else { - } - }, 500); + callback(true, "Error: Password not changed"); + } } else { callback(true, "Error: Password not changed"); + } @@ -2818,7 +2974,7 @@ function Engine() { //verify that it matches the current one $(progbar).width('40%'); - $(progmess).html('Securing password...'); + $(progmess).text('Securing password...'); setTimeout(function () { //if password reset do not pbkdf the password @@ -2831,13 +2987,13 @@ function Engine() { //get the two packets $(progbar).width('40%'); - $(progmess).html('Getting packets...'); + $(progmess).text('Getting packets...'); // $("#chngpwdprogbar").width('50%'); - //$("#chngpwdprogmess").html('Decrypting account packet...'); + //$("#chngpwdprogmess").text('Decrypting account packet...'); //decrypt with the old password var decryptedWithOld = true; var decryptedPayload = ''; @@ -2850,7 +3006,7 @@ function Engine() { if (decryptedWithOld) { $(progbar).width('80%'); - $(progmess).html('Securing new password...'); + $(progmess).text('Securing new password...'); API.getUserPacket(guid, sharedid, function (err, encpacket) { var decryptedUsrWithOld = true; @@ -2872,128 +3028,136 @@ function Engine() { }, function (err, response) { - //decrypt packet - var decryptedVerWithOld = true; - var jpacket = JSON.parse(response); - var veripacket = ''; - try { - veripacket = decryptNp(jpacket.packet, resetKey, jpacket.IV); - } - catch (verror) { - decryptedVerWithOld = false; - } - - - if (decryptedVerWithOld) { - - setTimeout(function () { + if (!err) { + //decrypt packet + var decryptedVerWithOld = true; + var jpacket = JSON.parse(response); + var veripacket = ''; + try { + veripacket = decryptNp(jpacket.packet, resetKey, jpacket.IV); + } + catch (verror) { + decryptedVerWithOld = false; + } - newpassword = pbkdf2(newpassword, oguid); + if (decryptedVerWithOld) { - $(progbar).width('80%'); - $(progmess).html('Encrypting account packet...'); + setTimeout(function () { - var newpayloadsuccess = true; - var newpayload = ''; - var newusrpayload = ''; - var newveripacket = ''; - var newpasspacket = ''; - var newAIV = ''; - var newUIV = ''; - var newRIV = ''; - var newPIV = '' - try { - newpayload = encrypt(decryptedPayload, newpassword); - newusrpayload = encrypt(rsaKeyPair, newpassword); - newveripacket = encryptNp(veripacket, newpassword); - newpasspacket = encryptNp(newpassword, decryptedPayload.hckey); + newpassword = pbkdf2(newpassword, oguid); - //and encrypt the new password with the hotkey seed - newAIV = newpayload.iv.toString(); - newUIV = newusrpayload.iv.toString(); - newRIV = newveripacket.iv.toString(); - newPIV = newpasspacket.iv.toString(); + $(progbar).width('80%'); + $(progmess).text('Encrypting account packet...'); - } catch (err) { - newpayloadsuccess = false; - } + var newpayloadsuccess = true; + var newpayload = ''; + var newusrpayload = ''; + var newveripacket = ''; + var newpasspacket = ''; + var newAIV = ''; + var newUIV = ''; + var newRIV = ''; + var newPIV = '' + try { - if (newpayloadsuccess) { + newpayload = encrypt(decryptedPayload, newpassword); + newusrpayload = encrypt(rsaKeyPair, newpassword); + newveripacket = encryptNp(veripacket, newpassword); + newpasspacket = encryptNp(newpassword, decryptedPayload.hckey); - //$("#chngpwdprogbar").width('90%'); - //$("#chngpwdprogmess").html('Encrypting user packet...'); + //and encrypt the new password with the hotkey seed - //test decryption - then update - var testpayload = ''; - var testnewusrpayload = ''; - var testveripacket = ''; - var testpasspacket = ''; - var testsuccess = true; - try { - testpayload = decrypt(newpayload.toString(), newpassword, newAIV); - testnewusrpayload = decrypt(newusrpayload.toString(), newpassword, newUIV); - testveripacket = decryptNp(newveripacket.toString(), newpassword, newRIV); - testpasspacket = decryptNp(newpasspacket.toString(), decryptedPayload.hckey, newPIV); + newAIV = newpayload.iv.toString(); + newUIV = newusrpayload.iv.toString(); + newRIV = newveripacket.iv.toString(); + newPIV = newpasspacket.iv.toString(); } catch (err) { - testsuccess = false; + newpayloadsuccess = false; } - if (testsuccess) { + if (newpayloadsuccess) { + + //$("#chngpwdprogbar").width('90%'); + //$("#chngpwdprogmess").text('Encrypting user packet...'); + + //test decryption - then update + var testpayload = ''; + var testnewusrpayload = ''; + var testveripacket = ''; + var testpasspacket = ''; + var testsuccess = true; + try { + testpayload = decrypt(newpayload.toString(), newpassword, newAIV); + testnewusrpayload = decrypt(newusrpayload.toString(), newpassword, newUIV); + testveripacket = decryptNp(newveripacket.toString(), newpassword, newRIV); + testpasspacket = decryptNp(newpasspacket.toString(), decryptedPayload.hckey, newPIV); + + } catch (err) { + testsuccess = false; + } - //save to the server - $(progbar).width('95%'); - $(progmess).html('Saving...'); + if (testsuccess) { + //save to the server + $(progbar).width('95%'); + $(progmess).text('Saving...'); - //TO DO: - //add in the re-encryption of the verification - //packet + //TO DO: + //add in the re-encryption of the verification + //packet - //if reset password then provide signed message and call reset function - var postData = { guid: guid, sharedid: sharedid, accountPacket: newpayload.toString(), userPacket: newusrpayload.toString(), verifyPacket: newveripacket.toString(), passPacket: newpasspacket.toString(), IVA: newAIV, IVU: newUIV, IVR: newRIV, PIV: newPIV }; - API.post("/api/1/u/updatepackets", postData, function (err, dataStr) { - if (err) { - callback(true, "Error: Password not changed"); - } else { + //if reset password then provide signed message and call reset function + + var postData = { guid: guid, sharedid: sharedid, accountPacket: newpayload.toString(), userPacket: newusrpayload.toString(), verifyPacket: newveripacket.toString(), passPacket: newpasspacket.toString(), IVA: newAIV, IVU: newUIV, IVR: newRIV, PIV: newPIV }; + API.post("/api/1/u/updatepackets", postData, function (err, dataStr) { + if (err) { + callback(true, "Error: Password not changed"); + } else { - if (dataStr == "ok") { + if (dataStr == "ok") { - callback(false, newpassword); + callback(false, newpassword); - } else { + } else { + + callback(true, "Error: Password not changed"); + } - callback(true, "Error: Password not changed"); } + }); + - } - }); + } else { + callback(true, "Error: Password not changed"); + } } else { callback(true, "Error: Password not changed"); } - } else { + }, 500); - callback(true, "Error: Password not changed"); + } else { - } - }, 500); + callback(true, "Error: Password not changed"); + } } else { callback(true, "Error: Password not changed"); + } @@ -3036,8 +3200,7 @@ function Engine() { API.post("/api/1/getemailvalidationtwofactor", { guid: m_this.m_guid, - token: vtoken, - status: 1 + token: vtoken }, function (err, response) { if (!err) { @@ -3076,9 +3239,16 @@ function Engine() { getAccountSettings(function (err, res) { - var settingsObject = JSON.parse(res); - m_this.m_settings = settingsObject; - callback(err, response); + if (!err) { + + var settingsObject = JSON.parse(res); + m_this.m_settings = settingsObject; + callback(err, response); + } else { + + callback(err, res); + } + }); } else { @@ -3095,8 +3265,7 @@ function Engine() { var postData = { guid: m_this.m_guid, - sharedid: m_this.m_sharedid, - twoFactorOnLogin: true + sharedid: m_this.m_sharedid }; API.post("/api/1/gettwofactorimg", postData, function (err, twoFactorQrImgUrl) { @@ -3122,6 +3291,7 @@ function Engine() { var walletInformation = {}; try { + walletInformation = decrypt(wallet.Payload, m_this.m_password, wallet.IV); var result = {}; @@ -3129,12 +3299,18 @@ function Engine() { getHotHash("", function (err, hotHash) { + if (!err) { + + result.hotHash = hotHash; + } + else { - result.hotHash = hotHash; + result.hotHash = "Unavailable"; + } walletInformation = {}; - callback(err, result); + callback(false, result); }); @@ -3229,6 +3405,15 @@ function Engine() { API.getCoinProfile(m_this.m_guid, m_this.m_sharedid, callback); } + this.getAccountData = getAccountData; + function getAccountData(callback) { + API.getAccountData(m_this.m_guid, m_this.m_sharedid, callback); + } + + this.getUserData = getUserData; + function getUserData(callback) { + API.getUserData(m_this.m_guid, m_this.m_sharedid, callback); + } this.getNickname = getNickname; function getNickname(callback) { diff --git a/src/ninki-ui-mobile.js b/src/ninki-ui-mobile.js index 55f5fd2..5e242da 100644 --- a/src/ninki-ui-mobile.js +++ b/src/ninki-ui-mobile.js @@ -1,10 +1,9 @@ var Bitcoin = require('bitcoinjs-lib'); var BIP39 = require('./bip39'); - -function UI() { - +var prettydate = require("pretty-date"); +function UI() { var Engine = new Ninki.Engine(); @@ -21,10 +20,13 @@ function UI() { var FRIENDSLIST = {}; var COINUNIT = 'BTC'; + var price = 0; var SELECTEDFRIEND = ''; var noAlert = false; var norefresh = false; + var sendmode = "std"; + var trasactionFilterOn = false; var allTransactions = []; var filteredTransactions = []; @@ -76,7 +78,7 @@ function UI() { corners: 1, // Corner roundness (0..1) rotate: 0, // The rotation offset direction: 1, // 1: clockwise, -1: counterclockwise - color: '#000', // #rgb or #rrggbb or array of colors + color: '#c6d0e3', // #rgb or #rrggbb or array of colors speed: 1, // Rounds per second trail: 60, // Afterglow percentage shadow: false, // Whether to render a shadow @@ -87,7 +89,27 @@ function UI() { left: '50%' // Left position relative to parent }; + /* Parse bitcoin URL query keys. */ + function parseBitcoinURL(url) { + var r = /^bitcoin:([a-zA-Z0-9]{27,34})(?:\?(.*))?$/; + var match = r.exec(url); + if (!match) return null; + + var parsed = { url: url } + + if (match[2]) { + var queries = match[2].split('&'); + for (var i = 0; i < queries.length; i++) { + var query = queries[i].split('='); + if (query.length == 2) { + parsed[query[0]] = decodeURIComponent(query[1].replace(/\+/g, '%20')); + } + } + } + parsed.address = match[1]; + return parsed; + } function setCookie(cname, cvalue) { @@ -203,2804 +225,1823 @@ function UI() { } - var profilepagestate = ''; - var networkpagestate = ''; - var friendpagestate = ''; - var menustate = ''; - var cl = ''; + function loginPIN() { - jQuery(document).ready(function () { + var pin = $("#loginpinno").val(); - var $body = jQuery('body'); + $("#enterpinalert").hide(); - /* bind events */ - $(document).on('focus', 'input', function (e) { - $(".footer").hide(); - }); + if (pin.length == 4) { + getCookie("guid", function (guid) { - $(document).on('blur', 'input', function (e) { - $(".footer").show(); - }); - $("#dashsend").hide(); - $("#dashreceive").hide(); - $("#dashcontact").hide(); + if (!Engine.m_appInitialised) { + Engine.m_oguid = guid; - $("#addcontactmodal").hide(); + var bytes = []; + for (var i = 0; i < guid.length; ++i) { + bytes.push(guid.charCodeAt(i)); + } + Engine.m_guid = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(bytes)).toString(); + } + Engine.getDeviceKey(pin, function (err, ekeyv) { - $('.num').bind('touchstart', function () { - $(this).removeClass('numtapoff'); + //decrypt the passcode - cl = 'b' + (Math.floor(Math.random() * 6) + 1) + ''; - //alert(cl); - $(this).addClass(cl); + if (!err) { - }) - $('.num').bind('touchend', function () { + if (Engine.m_appInitialised) { - var num = $(this); - var text = $.trim(num.find('.txt').clone().children().remove().end().text()); - var loginpinno = $('#loginpinno'); + $('.numdone').attr("style", "background-color:white"); - $(loginpinno).val(loginpinno.val() + text); + if (ekeyv.SessionToken) { + $("#API-Token").val(ekeyv.SessionToken); + } - if ($(loginpinno).val().length == 4) { - $("#pinscreen").hide(); + //check state and display correct headers - $("#btnLoginPIN").click(); - } + //set new session key + $("#paddel").hide(); + $('.numdone').attr("style", "background-color:white"); + $("#loginpin").hide(); + $("#nonlogin").show(); + $(".footer").show(); + $("#loginpinno").val(''); + //initialiseDashboard(); + setTimeout(updateUI(), 200); - var self = this; - setTimeout(function () { - //alert(cl); - $(self).removeClass('b1 b2 b3 b4 b5 b6'); - $(self).addClass('numtapoff'); - }, 100); + } else { - }) + $("#pinspinner").show(); + var target = document.getElementById('pinspinner'); + var spinner = new Spinner(spinneropts).spin(target); + getCookie("ninki_p", function (result) { + var enc = JSON.parse(result); + result = ''; + Engine.setStretchPass(Engine.decryptNp(enc.ct, ekeyv.DeviceKey, enc.iv)); + getCookie("ninki_rem", function (res) { - // $(".num").hammer({ - // drag: false, - // transform: false, - // hold: false, - // touch: false, - // tap: true, - // tapAlways: false, - // swipe: false, - // release: false, - // tapMaxTime: 1000 - // }).bind("tap", function (ev) { + if (res.length > 0) { + var enc = JSON.parse(res); + var fatoken = Engine.decryptNp(enc.ct, ekeyv.DeviceKey, enc.iv); - // $(this).addClass('numtap'); + //get the two factor token - // // var num = $(this); - // // var text = $.trim(num.find('.txt').clone().children().remove().end().text()); - // // var telNumber = $('#telNumber'); - // // $(telNumber).val(telNumber.val() + text); - // }); + //do we need to open wallet ? - // $(".num").click(function () { + Engine.openWallet(guid, fatoken, function (err, result) { - // $(this).addClass('numtap'); + if (!err) { - // // var num = $(this); - // // var text = $.trim(num.find('.txt').clone().children().remove().end().text()); - // // var telNumber = $('#telNumber'); - // // $(telNumber).val(telNumber.val() + text); - // }); + if (result.TwoFactorOnLogin) { + $("#pinspinner").hide(); + $("#loginpinno").val(''); + $("#enterpinalert").show(); + $("#enterpinalertmessage").text('Token has expired'); - $("#btnmenuprofile").hammer({ - drag: false, - transform: false, - hold: false, - touch: false, - tap: true, - tapAlways: false, - swipe: false, - release: false, - tapMaxTime: 1000 - }).bind("tap", function (ev) { - displayProfile(); + } else { + $("#pinspinner").hide(); + $('.numdone').attr("style", "background-color:white"); + $("#loginpin").hide(); + $("#loginpinno").val(''); + $("#paddel").hide(); - }); - $("#btnmenuprofile").hammer({ - drag: false, - transform: false, - hold: false, - touch: true, - tap: false, - tapAlways: false, - swipe: false, - release: false - }).bind("touch", function (ev) { + getCookie("currency", function (res) { - displayProfile(); + if (res) { + Engine.m_settings.LocalCurrency = res; - }); + } else { + setCookie("currency", Engine.m_settings.LocalCurrency); + } - $("#btnmenuprofile").hammer({ - drag: false, - transform: false, - hold: false, - touch: false, - tap: false, - tapAlways: false, - swipe: false, - release: true - }).bind("release", function (ev) { + var t = Engine.m_settings.LocalCurrency; + $('.sccy').filter(function () { + return $(this).text().trim() == t; + }).find("label").html(''); - displayProfile(); + getCookie("coinunit", function (res) { - }); + if (res) { - $("#btnmenuprofile").hammer({ - drag: false, - transform: false, - hold: true, - touch: false, - tap: false, - tapAlways: false, - swipe: false, - release: false - }).bind("hold", function (ev) { + Engine.m_settings.CoinUnit = res; - displayProfile(); + } else { + setCookie("coinunit", Engine.m_settings.CoinUnit); + } - }); - function displayProfile() { + var tc = Engine.m_settings.CoinUnit; + $('.scoinunit').filter(function () { + return $(this).text().trim() == tc; + }).find("label").html(''); + }); - if (menustate != 'profile') { - menustate = 'profile'; - $("#settings").hide(); - $("#network").hide(); - $("#dashboard").show(); - $("#networklist").hide(); - $("#invoices").hide(); - } else { - profilehome(); - } + }); - $("#btnmenusettings").attr('style', 'background-color:#ffffff'); - $("#btnmenunetwork").attr('style', 'background-color:#ffffff'); - $("#btnmenuprofile").attr('style', 'background-color:#eaeef1'); + initialiseDashboard(); + Engine.m_appInitialised = true; + } - } + } else { + $("#pinspinner").hide(); + $('.numdone').attr("style", "background-color:white"); - $("#btnmenunetwork").hammer({ - drag: false, - transform: false, - hold: false, - touch: false, - tap: true, - tapAlways: false, - swipe: false, - release: false, - tapMaxTime: 1000 - }).bind("tap", function (ev) { + } - displayNetwork(); + }); - }); + } - $("#btnmenunetwork").hammer({ - drag: false, - transform: false, - hold: false, - touch: true, - tap: false, - tapAlways: false, - swipe: false, - release: false - }).bind("touch", function (ev) { + }); - displayNetwork(); + }); - }); + } - $("#btnmenunetwork").hammer({ - drag: false, - transform: false, - hold: true, - touch: false, - tap: false, - tapAlways: false, - swipe: false, - release: true - }).bind("release", function (ev) { + } else { - displayNetwork(); + $("#pinspinner").hide(); - }); + if (ekeyv == "ErrDeviceDestroyed") { + deleteCookie("ninki_reg"); + deleteCookie("ninki_p"); + deleteCookie("ninki_rem"); + deleteCookie("guid"); + $("#loginpin").hide(); + $("#mainWallet").hide(); + $("#pairDevice").show(); - $("#btnmenunetwork").hammer({ - drag: false, - transform: false, - hold: true, - touch: false, - tap: false, - tapAlways: false, - swipe: false, - release: false - }).bind("hold", function (ev) { + location.reload(); + } - displayNetwork(); + $("#loginpinno").val(''); + $("#enterpinalert").show(); + $("#enterpinalertmessage").text(ekeyv); - }); + $('.numdone').attr("style", "background-color:white"); - function displayNetwork() { + } - if (menustate != "network") { - menustate = "network"; - $("#settings").hide(); - $("#network").show(); - $("#dashboard").hide(); - $("#networklist").show(); + }); + }); - if (networkpagestate == "invoice") { + } else { + $("#pinspinner").hide(); - $("#network").hide(); + } - $("#invoices").show(); - } + } - } else { - networkhome(); - } - $("#btnmenusettings").attr('style', 'background-color:#ffffff'); - $("#btnmenuprofile").attr('style', 'background-color:#ffffff'); - $("#btnmenunetwork").attr('style', 'background-color:#eaeef1'); - } + function closeSendNet() { + //$("#dashprofile").show(); + $("#dashsend").hide(); + $("#dashsendamt").hide(); + $("#mainWallet").show(); - $("#invformelink").hammer(null).bind("tap", function () { - $("#invformetab").show(); - $("#invbymetab").hide(); - $("#liby").removeClass('active'); - $("#lifor").addClass('active'); - }); + if (sendmode == "net") { + $("#friendheader").show(); + } - $("#invbymelink").hammer(null).bind("tap", function () { - $("#invbymetab").show(); - $("#invformetab").hide(); - $("#lifor").removeClass('active'); - $("#liby").addClass('active'); - }); + $(".footer").show(); - //tapsendfriend - //tapinvoicefriend - $("#tapsendfriend").hammer(null).bind("tap", function () { - $("#networksend").show(); - $("#pnlfriendinv").hide(); - networkpagestate = "friend"; - friendpagestate = "send"; - }); + $("#dashreceive").hide(); + $("#dashcontact").hide(); - $("#tapinvoicefriend").hammer(null).bind("tap", function () { - $("#pnlfriendinv").show(); - $("#networksend").hide(); - networkpagestate = "friend"; - friendpagestate = "invoice"; + $("#pinconfirm").hide(); - }); + $("#btnStdSndDone").hide(); - function networkhome() { - if (networkpagestate == "invoice") { - $('#network').show(); - $('#invoices').hide(); - networkpagestate = "friend"; - friendpagestate = "invoice"; + $('#toAddress').val(''); + $('#amount').text(''); - } else { - $("#pnlfriend").hide(); - $("#myfriends").show(); - $("#networklist").show(); - networkpagestate = ""; - } + updateStdAmount(); - } + } - function profilehome() { + function closeSendStd() { - $("#dashprofile").show(); - $("#dashsend").hide(); - $("#dashreceive").hide(); - $("#dashcontact").hide(); - $('#invoices').hide(); - $("#dashboard").show(); - profilepagestate = ""; + //$("#dashprofile").show(); + $("#dashsend").hide(); + $("#dashsendamt").hide(); + $("#dashheader").show(); + $("#mainWallet").show(); + $(".footer").show(); - } + $("#dashreceive").hide(); + $("#dashcontact").hide(); + $("#pinconfirm").hide(); - $("#btnmenusettings").hammer({ - drag: false, - transform: false, - hold: false, - touch: false, - tap: true, - tapAlways: false, - swipe: false, - release: false, - tapMaxTime: 1000 - }).bind("tap", function (ev) { + $("#addrfade").hide(); - menustate = "settings"; + $("#btnStdSndDone").hide(); - $("#settings").show(); - $("#network").hide(); - $("#networklist").hide(); - $("#dashboard").hide(); - $("#btnmenusettings").attr('style', 'background-color:#eaeef1'); - $("#btnmenuprofile").attr('style', 'background-color:#ffffff'); - $("#btnmenunetwork").attr('style', 'background-color:#ffffff'); - }); + //profilepagestate = "send"; + //menustate = "profile" - $("#tapsend").hammer(null).bind("tap", function () { - $("#dashprofile").hide(); - $("#dashsend").show(); - $("#dashreceive").hide(); - $("#dashcontact").hide(); - //$("#toAddress").focus(); - profilepagestate = "send"; - menustate = "profile" + $('#toAddress').val(''); + $('#amount').text(''); + updateStdAmount(); + } - }); + var stdAmountConvCoin = true; + var netAmountConvCoin = true; - $("#tapreceive").hammer(null).bind("tap", function () { - $("#dashprofile").hide(); - $("#dashsend").hide(); - $("#dashreceive").show(); - $("#dashcontact").hide(); - profilepagestate = "receive"; - menustate = "profile" + function convertToLocalCurrency(amount) { - }); + var conv = amount; + conv = conv * 1.0; - $("#taprequest").hammer(null).bind("tap", function () { - $("#dashprofile").hide(); - $("#dashsend").hide(); - $("#dashreceive").hide(); - $("#dashcontact").show(); - profilepagestate = "contact"; - menustate = "profile" + var sats = convertToSatoshis(conv, COINUNIT); + var btc = convertFromSatoshis(sats, "BTC"); - }); + var cbtc = btc * price; - $('#imgProfileContainer').show(); - $("#dropzone").hide(); - $("#btnSaveProfile").hide(); - $("#btnCancelProfile").hide(); - $("#statusedit").hide(); - $("#imgreset").hide(); + var loc = "en-US"; + var ires = cbtc; + if (Engine.m_settings.LocalCurrency == "JPY") { + ires = (cbtc * 1.0).toFixed(0) * 1.0; + } else { + ires = (cbtc * 1.0).toFixed(2) * 1.0; + } - $("#btnEditProfile").click(function () { - key = ''; + var cprc = ires.toLocaleString(loc, { style: "currency", currency: Engine.m_settings.LocalCurrency }); - $('#imgProfileContainer').hide(); - $("#dropzone").show(); - $("#btnSaveProfile").show(); - $("#btnCancelProfile").show(); - $("#btnEditProfile").hide(); - $("#statusedit").show(); - $("#profnmests").hide(); - $("#imgreset").show(); - $("#txtStatusText").val(Engine.m_statusText); + return cprc; - }); + } - $("#imgreset").click(function () { - Engine.m_profileImage = ""; - imgReset = true; + function convertFromLocalCurrency(amount) { - var imageSrc = "images/avatar/256px/Avatar-" + pad(Engine.m_nickname.length) + ".png"; + var conv = amount; + conv = conv * 1.0; - document.getElementById('imgProfile').src = imageSrc; - $('#imgProfileContainer').show(); - $('#dropzone').hide(); - $('progressNumber').html(''); - $("#imgreset").hide(); + //convert to bitcoin + if (price > 0) { + var cbtc = conv / price; - }); + var sats = convertToSatoshis(cbtc, "BTC"); + var btc = convertFromSatoshis(sats, COINUNIT); - var imgReset = false; - $("#btnSaveProfile").click(function () { + return btc; + } else { - //updateUserProfile + return 0; - var statusText = $("#txtStatusText").val(); + } - if (key == '' && !imgReset) { - key = Engine.m_profileImage; - } - Engine.updateUserProfile(key, statusText, Engine.m_invoiceTax, function (err, result) { + } - if (!err) { + function updateStdAmount() { - var imageSrc = "images/avatar/256px/Avatar-" + pad(Engine.m_nickname.length) + ".png"; - var imageSrcSmall = "images/avatar/64px/Avatar-" + pad(Engine.m_nickname.length) + ".png"; + var asamt = $('#amount').text(); + if (asamt == '' || asamt == '.') { + asamt = 0; + } - if (key != '' && !imgReset) { - imageSrc = "https://ninkip2p.imgix.net/" + key + "?crop=faces&fit=crop&h=256&w=256&mask=ellipse&border=1,d0d0d0"; - imageSrcSmall = "https://ninkip2p.imgix.net/" + key + "?crop=faces&fit=crop&h=64&w=64&mask=ellipse&border=1,d0d0d0"; - } + if (stdAmountConvCoin) { + $('#ccystdamt').text(convertToLocalCurrency(asamt)); + $('#hdamount').val(asamt); + } + else { + var amt = convertFromLocalCurrency(asamt); + $('#hdamount').val(amt); + $('#ccystdamt').text(amt + ' ' + COINUNIT); + } - $("#imgProfile").attr("src", imageSrc); - $("#imgtoprightprofile").attr("src", imageSrcSmall); + } - $('#imgProfileContainer').show(); - $("#dropzone").hide(); - $("#btnSaveProfile").hide(); - $("#btnCancelProfile").hide(); - $("#btnEditProfile").show(); - $("#statusedit").hide(); - $("#mystatus").html(statusText); - $("#txtStatusText").val(statusText); - $("#profnmests").show(); - $("#imgreset").hide(); - imgReset = false; - $("#profileimgfile").val(''); - $("#progressNumber").val(''); - } + var profilepagestate = ''; + var networkpagestate = ''; + var friendpagestate = ''; + var menustate = ''; - }); + var cl = ''; - }); + jQuery(document).ready(function () { - $("#btnCancelProfile").click(function () { + var $body = jQuery('body'); - $('#imgProfileContainer').show(); - $("#dropzone").hide(); - $("#btnSaveProfile").hide(); - $("#btnCancelProfile").hide(); - $("#btnEditProfile").show(); - //reset profile image + //guid + //ninki_reg - var imageSrc = "images/avatar/256px/Avatar-" + pad(Engine.m_nickname.length) + ".png"; + //if device is paired then - if (Engine.m_profileImage != '') { - imageSrc = "https://ninkip2p.imgix.net/" + Engine.m_profileImage + "?crop=faces&fit=crop&h=256&w=256&mask=ellipse&border=1,d0d0d0"; - } - $("#imgProfile").attr("src", imageSrc); + getCookie("ninki_reg", function (reg) { + + if (reg) { + $("#loginpin").show(); + } else { + $("#pairDevice").show(); + } - $("#statusedit").hide(); - $("#profnmests").show(); - $("#imgreset").hide(); }); - var obj = $("#dropzone"); - obj.click(function () { - $("#profileimgfile").click(); - }); + $("#mainWallet").hide(); + $("#dashreceive").hide(); + $("#dashcontact").hide(); - $("#profileimgfile").change(function (e) { - var control = document.getElementById("profileimgfile"); - var files = control.files; - //alert(files[0]); - //We need to send dropped files to Server - handleFileUpload(files, obj); + $("#addcontactmodal").hide(); - }); - obj.on('dragenter', function (e) { - e.stopPropagation(); - e.preventDefault(); - $(this).css('border', '2px solid #0B85A1'); - }); + $('#stdselcu').click(function () { - obj.on('dragover', function (e) { - e.stopPropagation(); - e.preventDefault(); - }); + var amttarget = '#amount'; - obj.on('drop', function (e) { + $('#stdselunit').text(COINUNIT); + stdAmountConvCoin = true; + $(amttarget).text(''); + updateStdAmount(); - $(this).addClass("b-dashed"); - $(this).addClass("b-light"); - e.preventDefault(); - var files = e.originalEvent.dataTransfer.files; - //alert(files[0]); - //We need to send dropped files to Server - handleFileUpload(files, obj); }); + $('#stdsellc').click(function () { - $(document).on('dragenter', function (e) { - e.stopPropagation(); - e.preventDefault(); - }); - $(document).on('dragover', function (e) { - e.stopPropagation(); - e.preventDefault(); - obj.css('border', '2px dotted #0B85A1'); - }); + var amttarget = '#amount'; - $(document).on('drop', function (e) { - e.stopPropagation(); - e.preventDefault(); - }); + $('#stdselunit').text(Engine.m_settings.LocalCurrency); + stdAmountConvCoin = false; + $(amttarget).text(''); + updateStdAmount(); - var key = ''; - function handleFileUpload(files, obj) { - if (files.length > 0) { - var file = files[0]; - var fd = new FormData(); + }); - key = "images\/" + Engine.m_nickname + '_' + (new Date).getTime() - Ninki.API.post("/api/1/u/createS3Policy", { test: 'test' }, function (err, result) { + // $('.numc').bind('touchstart', function () { + // $(this).removeClass('numtapoff'); - var policy = JSON.parse(result); + // cl = 'b' + (Math.floor(Math.random() * 6) + 1) + ''; + // //alert(cl); + // $(this).addClass(cl); - fd.append('key', key); - fd.append('acl', 'public-read'); - fd.append('Content-Type', file.type); - fd.append('bucket', 'ninkip2pimgstore'); - fd.append('AWSAccessKeyId', 'AKIAINOU56ATQFS3CLFQ'); - fd.append('policy', policy.s3Policy); - fd.append('signature', policy.s3Signature); - fd.append("file", file); - //fd.append("success_action_redirect", "https://localhost:1111/ok"); + // }); - var xhr = new XMLHttpRequest(); - xhr.upload.addEventListener("progress", uploadProgress, false); - xhr.addEventListener("load", uploadComplete, false); - xhr.addEventListener("error", uploadFailed, false); - xhr.addEventListener("abort", uploadCanceled, false); + $('.scoinunit').bind('click', function () { - xhr.open('POST', 'https://ninkip2pimgstore.s3-us-west-1.amazonaws.com/', true); //MUST BE LAST LINE BEFORE YOU SEND + $('.scoinunit').find("label").html(''); - xhr.send(fd); + $(this).find("label").html(''); - }); - } + var sel = $.trim($(this).text()); - } + setCookie("coinunit", sel); + Engine.m_settings.CoinUnit = sel; + COINUNIT = sel; - function uploadProgress(evt) { - if (evt.lengthComputable) { - var percentComplete = Math.round(evt.loaded * 100 / evt.total); - document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%'; - } - else { - document.getElementById('progressNumber').innerHTML = 'unable to compute'; - } - } + updateUI(); - function uploadComplete(evt) { - /* This event is raised when the server send back a response */ - //alert("Done - " + evt.target.responseText); - document.getElementById('imgProfile').src = 'https://ninkip2p.imgix.net/' + key + "?fit=crop&crop=faces&h=128&w=128&mask=ellipse&border=1,d0d0d0"; - $('#imgProfileContainer').show(); - $('#dropzone').hide(); - $('progressNumber').html(''); - $("#imgreset").hide(); + }); - } - function uploadFailed(evt) { - alert("There was an error attempting to upload the file." + evt); - } - function uploadCanceled(evt) { - alert("The upload has been canceled by the user or the browser dropped the connection."); - } - var options = {}; - options.ui = { - container: "#pwd-container", - showVerdictsInsideProgressBar: true, - showPopover: true, - showErrors: true, - viewports: { - progress: ".pwstrength_viewport_progress" - } - }; - options.common = { - debug: true, - onLoad: function () { - $('#messages').text('Start typing password'); - }, - onKeyUp: function () { - $("#createwalletalert").fadeOut(100); - } - }; + $('.sccy').bind('click', function () { - $('#createWalletStart #cpassword').pwstrength(options); + $('.sccy').find("label").html(''); + $(this).find("label").html(''); - var optionschng = {}; - optionschng.ui = { - container: "#newpwd-container", - showVerdictsInsideProgressBar: true, - showPopover: true, - showErrors: true, - viewports: { - progress: ".newpwstrength_viewport_progress" - } - }; - optionschng.common = { - debug: true, - onLoad: function () { - $('#messages').text('Start typing password'); - }, - onKeyUp: function () { - $("#createwalletalert").fadeOut(100); - } - }; + var sel = $.trim($(this).text()); - $('#newpassword1').pwstrength(optionschng); + setCookie("currency", sel); - }); + Engine.m_settings.LocalCurrency = sel; + updateUI(); + }); - $('#btnPassphraseLogin').keydown(function (e) { - if (e.keyCode == 13) { - e.preventDefault(); - return false; - } - }); - $('#frmSaveTwoFactor').keydown(function (e) { - if (e.keyCode == 13) { - e.preventDefault(); - return false; - } - }); + $('.numc').bind('touchend', function () { - $('#phrase2fa').keydown(function (e) { - if (e.keyCode == 13) { - e.preventDefault(); - return false; - } - }); + var num = $(this); + var text = $.trim(num.find('.txt').clone().children().remove().end().text()); + var amttarget = '#amount'; - $(document).on("keydown", function (e) { - if (e.which === 8 && !$(e.target).is("input, textarea")) { - e.preventDefault(); - } - }); + var amt = $(amttarget).text(); + if (!(amt.indexOf(".") > -1 && text == '.')) { - $(document).ready(function () { + var prev = amt.substring(0, amt.length - 1); + + if (text.length > 0) { + $(amttarget).text($(amttarget).text() + text); + } else { + $(amttarget).text(prev); + } + updateStdAmount(); - $('body').on('click', function (e) { - //did not click a popover toggle or popover - if ($(e.target).data('toggle') !== 'popover' - && $(e.target).parents('.popover.in').length === 0) { - $('[data-toggle="popover"]').popover('hide'); } + + }); + var pintaps = 0; + var prevpin = ''; + //touchend + $('#loginpin .num').bind('touchstart', function () { + var num = $(this); + var text = $.trim(num.find('.txt').clone().children().remove().end().text()); - getCookie('guid', function (res) { - if (res.length == 0) { + if (text.length > 0) { - var betafrom = 'December 12, 2009 12:00 pm GMT'; - var betato = 'December 12, 2009 01:00 pm GMT'; + pintaps++; - betafrom = getLocalTime(betafrom); - betato = getLocalTime(betato); + if (pintaps == 1) { - $('#betafrom').html(betafrom); - $('#betato').html(betato); + $('#loginpin #pin1').attr("style", "background-color:Gray"); - $('#basicModal').modal('show'); + } - $("#btnDeclineBeta").click(function () { - window.location.href = '/' - }); + if (pintaps == 2) { - } - }); + $('#loginpin #pin2').attr("style", "background-color:Gray"); + } + if (pintaps == 3) { - $("#btnAcceptBeta").click(function () { - $("#openWalletStart #password").focus(); - }); + $('#loginpin #pin3').attr("style", "background-color:Gray"); + } + if (pintaps == 4) { + $('#loginpin #pin4').attr("style", "background-color:Gray"); + } - $("#btncreatewallet").click(function () { - showCreateWalletStart(); - }); + } - $("#pairdeviceblob").change(function () { - $("#loginpin").hide(); - $("#pairstep1").hide(); - $("#pairstep2").show(); + var loginpinno = $('#loginpinno'); + var lpin = loginpinno.val(); + prevpin = lpin.substring(0, lpin.length - 1) - }); + if (text.length > 0) { + $('#paddel').show(); - $("#btnUnpair").click(function () { - getCookie("guid", function (guid) { - Engine.m_oguid = guid; + $(loginpinno).val(loginpinno.val() + text); - var bytes = []; - for (var i = 0; i < guid.length; ++i) { - bytes.push(guid.charCodeAt(i)); - } + if (pintaps == 4) { - Engine.m_guid = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(bytes)).toString(); + pintaps = 0; - Engine.destroyDevice(function (err, res) { + loginPIN(); - deleteCookie("ninki_rem"); - deleteCookie("ninki_p"); - deleteCookie("ninki_reg"); - deleteCookie("ninki_h"); + //only if fail - //call to server - location.reload(); + } - }); - }); + } else { - }); + if (pintaps == 1) { - $("#btnPairDevice").click(function () { + $('#loginpin #pin1').attr("style", "background-color:White"); + $('#loginpin #paddel').hide(); - var deviceid = "DEVICE123456789"; + } - if (window.cordova) { - deviceid = window.device.uuid; - } + if (pintaps == 2) { - var blob = $('#pairdeviceblob').val(); - var pin = $('#pairdevicepinnumber').val(); - var pwd = $('#pairpwd').val(); + $('#loginpin #pin2').attr("style", "background-color:White"); + } + if (pintaps == 3) { - var splitBlob = blob.split('|'); + $('#loginpin #pin3').attr("style", "background-color:White"); - var enck = splitBlob[0]; - var iv = splitBlob[1]; - var guid = splitBlob[2]; - var deviceName = splitBlob[3]; - var regToken = splitBlob[4]; + } + if (pintaps == 4) { - Engine.setPass(pwd, guid); + $('#loginpin #pin4').attr("style", "background-color:White"); - pwd = Engine.m_password; + } + + $(loginpinno).val(prevpin); + + if (pintaps > 0) { + pintaps--; + } - var bytes = []; - for (var i = 0; i < guid.length; ++i) { - bytes.push(guid.charCodeAt(i)); } - var hashguid = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(bytes)).toString(); + }); - Engine.m_guid = hashguid; - Engine.m_oguid = guid; - //first validate the password with the secret - Engine.getRecoveryPacket(function (err, response) { + $('#pinconfirm .num').bind('touchend', function () { - if (err) { + var num = $(this); + var text = $.trim(num.find('.txt').clone().children().remove().end().text()); + var loginpinno = $('#sendstdpin'); + var lpin = loginpinno.val(); + prevpin = lpin.substring(0, lpin.length - 1) - $('#pairdevicealertmessage').html(response); + if (text.length > 0) { - } else { + $('#paddelconf').show(); - //decrypt packet + pintaps++; - var jpacket = JSON.parse(response); + if (pintaps == 1) { - var secret = Engine.decryptNp(jpacket.packet, pwd, jpacket.IV); + $('#pinconfirm #cpin1').attr("style", "background-color:Gray"); - Engine.validateSecret(secret, function (err, secvalid) { + } - if (!err) { + if (pintaps == 2) { + $('#pinconfirm #cpin2').attr("style", "background-color:Gray"); - //hash the pin and device id + } - var pinhash = deviceid + pin; - bytes = []; - for (var i = 0; i < pinhash.length; ++i) { - bytes.push(pinhash.charCodeAt(i)); - } + if (pintaps == 3) { - pinhash = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(bytes)).toString(); + $('#pinconfirm #cpin3').attr("style", "background-color:Gray"); + } - //new register device + if (pintaps == 4) { + $('#pinconfirm #cpin4').attr("style", "background-color:Gray"); - //enter password - //stretch - //get validate - //if valid - //choose a PIN - //register + } - var devplatform = "platform"; - var devmodel = "model"; + $(loginpinno).val(loginpinno.val() + text); - if (window.cordova) { - devplatform = window.device.platform; - devmodel = window.device.model; - } + if (pintaps == 4) { - Engine.registerDevice(hashguid, deviceName, devplatform, devmodel, pinhash, regToken, secret, function (err, result) { + pintaps = 0; - if (!err) { + if (sendmode == 'std') { - var dk = JSON.parse(result); + sendMoneyStd(); - if (dk.DeviceKey.length > 0) { + } else if (sendmode == 'net') { - var decblob = Engine.decryptNp(enck, dk.DeviceKey, iv); + sendMoney(SELECTEDFRIEND, 0); - //slice it up - //64 64 64 - var hk = decblob.substring(0, 64); - var fatoken = decblob.substring(64, 128); + } else if (sendmode == 'inv') { - var encp = Engine.encryptNp(pwd, dk.DeviceKey); - result = ''; + payInvoice(selectedInvoiceUserName, selectedInvoiceAmount, selectedInvoiceId); - var ptok = {}; - ptok.ct = encp.toString(); - ptok.iv = encp.iv.toString(); - var ptoken = JSON.stringify(ptok); + } - var enc = Engine.encryptNp(fatoken, dk.DeviceKey); - var ctok = {}; - ctok.ct = enc.toString(); - ctok.iv = enc.iv.toString(); - var ctoken = JSON.stringify(ctok); + //only if fail + } - var ench = Engine.encryptNp(hk, dk.DeviceKey); - var htok = {}; - htok.ct = ench.toString(); - htok.iv = ench.iv.toString(); - var hkey = JSON.stringify(htok); + } else { - dk.DeviceKey = ''; - //login using the credentials - //get a session - //then call register PIN - //this will return the encryption key - //encrypt the password and store in local storage - setCookie("guid", guid); + if (pintaps == 1) { - Engine.openWallet(guid, fatoken, function (err, result) { + $('#pinconfirm #cpin1').attr("style", "background-color:White"); + $('#pinconfirm #paddelconf').hide(); - if (!err) { + } - if (!result.TwoFactorOnLogin) { + if (pintaps == 2) { - setCookie("ninki_rem", ctoken); - setCookie("ninki_p", ptoken); - setCookie("ninki_reg", regToken); - setCookie("ninki_h", hkey); + $('#pinconfirm #cpin2').attr("style", "background-color:White"); - $('#pairDevice').hide(); + } - initialiseUI(); + if (pintaps == 3) { - } else { + $('#pinconfirm #cpin3').attr("style", "background-color:White"); + } - $('#pairdevicealertmessage').html("could not pair"); - $('#pairdevicealert').show(); - } + if (pintaps == 4) { + $('#pinconfirm #cpin4').attr("style", "background-color:White"); - } else { + } - $('#pairdevicealertmessage').html(result); - $('#pairdevicealert').show(); - } + $(loginpinno).val(prevpin); - }); - } else { + if (pintaps > 0) { + pintaps--; + } - $('#pairdevicealertmessage').html("The pairing token has expired"); - $('#pairdevicealert').show(); - } + } - } else { + }); - $('#pairdevicealertmessage').html(result); - $('#pairdevicealert').show(); - } + $("#btnmenuprofile").bind('touchstart', function () { - }); + displayProfile(); - } else { + }); - $('#pairdevicealertmessage').html(secvalid); - $('#pairdevicealert').show(); - } - }); + function displayProfile() { - } - }); + if (menustate != 'profile') { + menustate = 'profile'; + $("#settings").hide(); + $("#settingsheader").hide(); - }); + $("#network").hide(); + $("#networklistheader").hide(); + $("#friendheader").hide(); + $("#dashboard").show(); - $("#btnLoginPIN").click(function () { + $('#dashheader').show(); + //$("#invoices").hide(); - var pin = $("#loginpinno").val(); + } else { + profilehome(); + } - $("#enterpinalert").hide(); + $("#btnmenusettings").attr('style', 'background-color:#ffffff'); + $("#btnmenunetwork").attr('style', 'background-color:#ffffff'); + $("#btnmenuprofile").attr('style', 'background-color:#eaeef1'); - if (pin.length == 4) { + } - getCookie("guid", function (guid) { - Engine.m_oguid = guid; + var hastouched = false; + $("#btnmenunetwork").bind('touchstart', function () { - var bytes = []; - for (var i = 0; i < guid.length; ++i) { - bytes.push(guid.charCodeAt(i)); - } + if (!hastouched) { - Engine.m_guid = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(bytes)).toString(); + hastouched = true; + var target = document.getElementById('myfrndspin'); + var spinner = new Spinner(spinneropts).spin(target); + $("#myfrndspin").show(); + updateFriends(function (err, res) { - Engine.getDeviceKey(pin, function (err, ekeyv) { + $("#myfrndspin").hide(); - //decrypt the passcode + }); - if (!err) { + loadInvoices(); - getCookie("ninki_p", function (result) { + } - var enc = JSON.parse(result); - result = ''; - Engine.setStretchPass(Engine.decryptNp(enc.ct, ekeyv.DeviceKey, enc.iv)); + displayNetwork(); - getCookie("ninki_rem", function (res) { - if (res.length > 0) { - var enc = JSON.parse(res); - var fatoken = Engine.decryptNp(enc.ct, ekeyv.DeviceKey, enc.iv); + }); - //get the two factor token - //do we need to open wallet ? - if (!Engine.m_appInitialised) { - Engine.openWallet(guid, fatoken, function (err, result) { + function displayNetwork() { - if (!err) { + if (menustate != "network") { - if (result.TwoFactorOnLogin) { + menustate = "network"; + $("#settings").hide(); + $("#settingsheader").hide(); + $("#dashboard").hide(); + $('#dashheader').hide(); + //$("#pnlfriend").hide(); + $("#network").show(); - $("#loginpinno").val(''); - $("#enterpinalert").show(); - $("#enterpinalertmessage").html('Token has expired'); - } else { + if ($("#networklist").is(':visible')) { + $("#networklistheader").show(); + } - $("#loginpin").hide(); - $("#loginpinno").val(''); + if ($("#pnlfriend").is(':visible')) { + $("#friendheader").show(); + } - initialiseUI(); - Engine.m_appInitialised = true; - } + //$("#networklist").show(); - } else { + if (networkpagestate == "invoice") { - } - }); + //$("#invoices").show(); + } - } else { + } else { - if (ekeyv.SessionToken) { - $("#API-Token").val(ekeyv.SessionToken); - } - //set new session key + networkhome(); + } - $("#loginpin").hide(); - $("#loginpinno").val(''); + $("#btnmenusettings").attr('style', 'background-color:#ffffff'); + $("#btnmenuprofile").attr('style', 'background-color:#ffffff'); + $("#btnmenunetwork").attr('style', 'background-color:#eaeef1'); + } - initialiseUI(); - } + $("#invformelink").hammer(null).bind("tap", function () { - } + sendmode = "inv"; + $("#invformetab").show(); + $("#invbymetab").hide(); + $("#liby").removeClass('active'); + $("#lifor").addClass('active'); + }); - }); + $("#invbymelink").hammer(null).bind("tap", function () { + $("#invbymetab").show(); + $("#invformetab").hide(); + $("#lifor").removeClass('active'); + $("#liby").addClass('active'); + }); - }); + //tapsendfriend + //tapinvoicefriend - } else { + //tapnetpayments - if (ekeyv == "ErrDeviceDestroyed") { + $("#tapnetpayments").hammer(null).bind("tap", function () { + $("#pnlfriendinv").hide(); + $("#networkpayments").show(); + $("#networksend").hide(); + networkpagestate = "friend"; + friendpagestate = "payments"; - deleteCookie("ninki_reg"); - deleteCookie("ninki_p"); - deleteCookie("ninki_rem"); - deleteCookie("guid"); + }); - location.reload(); - } - $("#loginpinno").val(''); - $("#enterpinalert").show(); - $("#enterpinalertmessage").html(ekeyv); + $("#tapinvoicefriend").hammer(null).bind("tap", function () { - } + $("#pnlfriendinv").show(); + $("#networkpayments").hide(); + $("#networksend").hide(); + networkpagestate = "friend"; + friendpagestate = "invoice"; - }); + }); - }); + function networkhome() { + if (networkpagestate == "invoice") { - } + $('#network').show(); + $("#pnlfriend").show(); + $("#friendheader").show(); + $('#invoices').hide(); + networkpagestate = "friend"; + friendpagestate = "invoice"; - }); - $("#btnLogin").click(function () { + } else { - if (!ensureOpenWalletGuidAndPasswordValid()) return; + $("#pnlfriend").hide(); + $("#friendheader").hide(); + $("#network").show(); + $("#networklist").show(); + $("#networklistheader").show(); - $("#imgopenwaiting").show(); - $("#btnLogin").prop('disabled', true); - $("#btnLogin").addClass('disabled'); - var target = document.getElementById('imgopenwaiting'); - var spinner = new Spinner(spinneropts).spin(target); + networkpagestate = ""; + } + } - setTimeout(function () { + function profilehome() { - var guid = $('#openWalletStart input#guid').val(); - var password = $('#openWalletStart input#password').val(); - var twoFactorCode = $('#openWalletStart input#twoFactorCode').val(); - //decrypt the password using the key sent back from the server + $("#dashprofile").show(); + $("#dashsend").hide(); + $("#dashreceive").hide(); + $("#dashcontact").hide(); + $('#invoices').hide(); + $("#dashboard").show(); + $('#dashheader').show(); + $("#network").hide(); + profilepagestate = ""; + } - Engine.setPass(password, guid); - getCookie("ninki_rem", function (res) { + $("#btnmenusettings").bind('touchstart', function () { - if (res.length > 0) { - var enc = JSON.parse(res); - twoFactorCode = Engine.decryptNp(enc.ct, Engine.m_password, enc.iv); - } + menustate = "settings"; - setCookie('guid', guid); + $("#settings").show(); + $("#settingsheader").show(); + $("#network").hide(); + $("#dashboard").hide(); + $('#dashheader').hide(); + $('#friendheader').hide(); + $('#networklistheader').hide(); - Engine.openWallet(guid, twoFactorCode, function (err, result) { + $("#btnmenusettings").attr('style', 'background-color:#eaeef1'); + $("#btnmenuprofile").attr('style', 'background-color:#ffffff'); + $("#btnmenunetwork").attr('style', 'background-color:#ffffff'); + }); - $("#imgopenwaiting").hide(); - $("#btnLogin").prop('disabled', false); - $("#btnLogin").removeClass('disabled'); - if (!err) { + $('#toAddress').change(function () { - $("#imgopenwaiting").hide(); - $("#openwalletalert").hide(); + //if a valid bitcoin address then + //next stage + var addr = $('#toAddress').val(); - if (result.TwoFactorOnLogin) { + var paddr = parseBitcoinURL(addr); - //delete any old 2 factor tokens + if (addr.length > 25) { + if (Engine.isAddressValid(paddr.address)) { - deleteCookie("ninki_rem"); + //next stage - if (!result.Beta12fa) { + //if amount is included in the URL set the amount and go straight to the + //pay screen + $('#toAddress').val(paddr.address) - $('#openWalletStart input#password').val(''); + $("#dashsend").hide(); + $("#addrfade").hide(); + $("#dashsendamt").show(); - if (result.TwoFactorOnLogin) { - $("#siguid").hide(); - $("#silguid").hide(); - $("#sipwd").hide(); - $("#si2fa").show(); - $("#sib1").hide(); - $("#sib2").show(); - $('#openWalletStart input#twoFactorCode').focus(); - } - } else { + } + } + }); - //for beta1 migrations - $("#siguid").hide(); - $("#silguid").hide(); - $("#sipwd").hide(); - $("#si2fa").show(); - $("#sib1").hide(); - $("#sib2").show(); - $('#openWalletStart input#twoFactorCode').focus(); - } + $("#btnCloseContact").bind('touchstart', function () { - } else { + //closeSendStd(); + $("#dashcontact").hide(); + $("#mainWallet").show(); + $("#networklistheader").show(); + $(".footer").show(); + }); - //initiate 2fa setup modal - if (!m_this.m_twoFactorOnLogin) { - $("#twofactorsettings").show(); - $("#2famodal").modal('show'); + $("#btnAddContactDone").bind('touchstart', function () { - $("#twofactorsettings").show(); - $("#btnSetupTwoFactor").hide(); - $("#savetwofactorerror").hide(); - $("#setup2faemail").hide(); - $("#setup2faqr").show(); + $("#addcontactmodal").hide(); + $("#dashcontact").show(); - showSettingsTwoFactorQr(); - } else { + }); - initialiseUI(); + $("#btnCloseStdSndAmt").bind('touchstart', function () { - } + closeSendNet(); - } + }); - $("#unlockaccount").hide(); + $("#btnCloseStdSndPIN").bind('touchstart', function () { - } else { - $("#imgopenwaiting").hide(); - $("#openwalletalert").show(); + if (sendmode == "std") { + closeSendStd(); + } else { + closeSendNet(); + } - if (result == "ErrAccount") { - $("#openwalletalertmessage").html("Incorrect password"); - } + }); - if (result == "ErrLocked") { - $("#openwalletalertmessage").html("Your account has been locked."); - $("#unlockaccount").show(); - } else { - $("#unlockaccount").hide(); - } - } + $("#btnCloseStdSnd").bind('touchstart', function () { - }); + closeSendStd(); - }); - }, 100); }); + $("#btnCloseRec").bind('touchstart', function () { - $("#btn2faLogin").click(function () { + closeSendStd(); + }); - $("#img2faopenwaiting").show(); - $("#btn2faLogin").prop('disabled', true); - $("#btn2faLogin").addClass('disabled'); - var target = document.getElementById('img2faopenwaiting'); - var spinner = new Spinner(spinneropts).spin(target); - setTimeout(function () { + $("#btnStdSndDone").bind('touchstart', function () { - var twoFactorCode = $('#openWalletStart input#twoFactorCode').val(); - var rememberTwoFactor = $('#twofactorremember')[0].checked; + $('#sendprogress').hide(); - Engine.openWallet2fa(twoFactorCode, rememberTwoFactor, function (err, result) { - if (err) { + if (sendmode == "std") { + closeSendStd(); + } else { + closeSendNet(); + } + + }); - $("#img2faopenwaiting").hide(); - $("#openwalletalert").show(); - $("#openwalletalertmessage").html(result); - $("#btn2faLogin").prop('disabled', false); - $("#btn2faLogin").removeClass('disabled'); - } else { + //$("#btnStdSndDone") - if (result.CookieToken) { + $("#btnsendmoneystd").bind('touchstart', function () { - setCookie("ninki_rem", result.CookieToken); - } + if (sendmode == 'std') { + $("#sendstds2add").text($('#toAddress').val()); + } else if (sendmode == 'net') { + $("#sendstds2add").text(SELECTEDFRIEND); + } + $("#sendstds2amt").text($("#hdamount").val() + ' ' + COINUNIT); - initialiseUI(); - } - }); + $("#dashsend").hide(); + $("#dashsendamt").hide(); + $("#pinconfirm").show(); - }, 100); + //sendMoneyStd(); }); - $("#btnEmailGuid").click(function () { - - var userName = $("#txtlostguidusername").val(); - Engine.emailGUID(userName, function (err, response) { + $("#btnCloseValidate").bind('touchstart', function () { - showOpenWalletStart(); - }); + $("#friendheader").show(); + $("#mainWallet").show(); + $(".footer").show(); + $("#networkvalidate").hide(); }); - $("#btnaddfriend").click(function () { + $("#tapvalidatefriend").bind('touchstart', function () { - addFriend($('input#friend').val()); + $("#friendheader").hide(); + $("#mainWallet").hide(); + $(".footer").hide(); + $("#networkvalidate").show(); }); - $("#btngenaddr").click(function () { + $("#tapsendfriend").bind('touchstart', function () { - generateAddressClient(); + sendmode = "net"; - }); - - - $("#showopenwallet").click(function () { - - showOpenWalletStart(); - - }); - - $("#btnopenwalletrec").click(function () { - - showOpenWalletStart(); + $("#sendsubheading").text("send to " + SELECTEDFRIEND); - }); - - - $("#showopenwalletcr").click(function () { - - showOpenWalletStart(); + $("#btnStdSndDone").hide(); + $("#dashsend").hide(); + $("#addrfade").hide(); - }); + $("#friendheader").hide(); + $("#dashsendamt").show(); + $("#mainWallet").hide(); + $(".footer").hide(); - $("#btnsendmoneystd").hammer(null).bind("tap", function () { - sendMoneyStd(); + networkpagestate = "friend"; + friendpagestate = "send"; }); + $("#tapsend").bind('touchstart', function () { - $("#btnCreate").click(function () { - - if ($("#frmcreate").parsley('validate')) { - - //check password strength - if (($(".password-verdict").html() == 'Strong' || $(".password-verdict").html() == 'Very Strong')) { - - //can we remove this check? - if (ensureCreateWalletGuidNicknameAndPasswordValid()) { - - $("#imgcreatewaiting").show(); - $("#btnCreate").prop('disabled', true); - $("#btnCreate").addClass('disabled'); - $("#lnkOpenWallet").hide(); - - var target = document.getElementById('imgcreatewaiting'); - var spinner = new Spinner(spinneropts).spin(target); - - //error handling here? - - var guid = $('#createWalletStart input#guid').val(); - var username = $("#createWalletStart input#nickname").val(); - var password = $('#createWalletStart input#cpassword').val(); - var emailAddress = $('#createWalletStart input#emailaddress').val(); - - - Engine.createWallet(guid, password, username, emailAddress, function (err, result) { - - //move error handling and ui elements to here - $("#createWalletStart input#nickname").css("border-color", "#ccc"); - if (err) { - if (result == "ErrUserExists") { - - $("#createWalletStart input#nickname").css("border-color", "#ffaaaa"); - $("#imgcreatewaiting").hide(); - - $("#createwalletalert").show(); - $("#createwalletalertmessage").html("The username already exists"); - - $("#btnCreate").prop('disabled', false); - $("#btnCreate").removeClass('disabled'); - $("#lnkOpenWallet").show(); - } - if (result == "ErrEmailExists") { + sendmode = "std" - $("#createWalletStart input#emailaddress").css("border-color", "#ffaaaa"); - $("#imgcreatewaiting").hide(); - - $("#createwalletalert").show(); - $("#createwalletalertmessage").html("The email address is already in use"); - - $("#btnCreate").prop('disabled', false); - $("#btnCreate").removeClass('disabled'); - $("#lnkOpenWallet").show(); - } - - if (result == "ErrCreateAccount") { - - $("#imgcreatewaiting").hide(); - $("#btnCreate").prop('disabled', false); - $("#btnCreate").removeClass('disabled'); - $("#lnkOpenWallet").show(); - - } + $("#dashheader").hide(); + $("#dashprofile").hide(); + $("#dashsend").show(); - } else { - //set variables for the session - $("#createWalletStart").hide(); - $('#createWalletStart input#cpassword').val(''); - $('#createWalletStart input#password1').val(''); + setTimeout(function () { + $("#addrfade").fadeIn(500); - $("#hotWalletPhrase").text(result.hotWalletPhrase); - $("#coldWalletPhrase").text(result.coldWalletPhrase); - //$("#ninkiWalletPhrase").text(result.ninkiWalletPhrase); + }, 500); - $("#walletGuid").text($('input#guid').val()); - $("#showPhrases").show(); - $("#securitywizard").show(); - if ($('#createWalletStart input#showQrCheckbox')[0].checked) { - //create two factor setting in databse and display qr code - $("#no2famessage").hide(); - showTwoFactorQr(); - } else { - $("#no2famessage").show(); - } - } - }); - } + $("#dashsendamt").hide(); + $("#mainWallet").hide(); + $(".footer").hide(); - } else { + $("#dashreceive").hide(); + $("#dashcontact").hide(); + $("#toAddress").blur(); + $("#qr").focus(); + $("#btnStdSndDone").hide(); - //password not strong - $("#createwalletalert").show(); - $("#createwalletalertmessage").html("Password must be Strong- ideally Very Strong"); - } + profilepagestate = "send"; + menustate = "profile" - } }); - $("#btnPassphraseLogin").click(function () { + $("#tapreceive").bind('touchstart', function () { - var isvalid = true; - - if ($('#createWalletStart input#showQrCheckbox')[0].checked) { - isvalid = $("#phrase2fa").parsley('validate'); - } - - if (isvalid) { - - var twoFactorCodeChk = $('#twoFactorCodeCheck').val(); - - var target = document.getElementById('imgphrasewaiting'); - var spinner = new Spinner(spinneropts).spin(target); - - $("#imgphrasewaiting").show(); - setCookie('guid', Engine.m_oguid); - - Engine.openWalletAfterCreate(twoFactorCodeChk, function (err, result) { - - if (err) { - - $("#imgphrasewaiting").hide(); - $("#phraseloginerror").show(); - $("#phraseloginerrormessage").html(result); - - } else { - - - initialiseUI(); - $("#imgphrasewaiting").hide(); - $("#phraseloginerror").hide(); - $("#validateemail").show(); - $("#step4").show(); - $("#step3").hide(); - $("#listep3").removeClass("active"); - $("#listep4").addClass("active"); - $("#prgsecwiz").width('100%'); - $(".next").hide(); - $(".previous").hide(); - } - - - }); - } + //dashreceive + $("#dashheader").hide(); + $("#dashprofile").hide(); + $("#dashsend").hide(); + $("#mainWallet").hide(); + $("#dashreceive").show(); + $(".footer").hide(); + $("#dashcontact").hide(); + profilepagestate = "receive"; + menustate = "profile" }); + $("#taprequest").bind('touchstart', function () { + //$("#dashprofile").hide(); + //$("#dashsend").hide(); + //$("#dashreceive").hide(); + $("#mainWallet").hide(); + $("#networklistheader").hide(); + $("#dashcontact").show(); + $(".footer").hide(); - $("#btnEmailValidate").click(function () { - - var token = $("#txtEmailToken").val(); - - Engine.getEmailValidation(token, function (err, response) { - - if (err) { - - } else { - - if (response != "Valid") { - $("#valemailerror").show(); - - if (response == "Expired") { - $("#valemailerrormessage").html('Your token has expired'); - } - if (response == "Invalid") { - $("#valemailerrormessage").html('Your token is not valid'); - } - - - - } else { - - if ($('#createWalletStart input#showQrCheckbox')[0].checked) { - //TWOFACTORONLOGIN = true; - } - - //initialiseUI(); - Engine.m_validate = false; - - //readAccountSettingsFromServerAndPopulateForm(); - $("#securitywizard").hide(); - $("#validateemail").hide(); - $("#mainWallet").show(); - $("#valemailerror").hide(); - } - } - - }); - - - //call to verify token + //checkAndValidateTimer = setInterval(function () { checkAndValidateFriendRequests() }, 2000); + //profilepagestate = "contact"; + //menustate = "profile" }); - //wallet security wizard - var step = 1; - $("#step1").show(); - $("#prgsecwiz").width('25%'); - $(".previous").hide(); - $(".next").click(function () { - - if (step == 2) { - $("#step3").show(); - $("#step2").hide(); - $("#listep2").removeClass("active"); - $("#listep3").addClass("active"); - $("#prgsecwiz").width('75%'); - $(".next").hide(); - $(".previous").show(); - step++; - } - - if (step == 1) { - $("#step2").show(); - $("#step1").hide(); - $("#listep1").removeClass("active"); - $("#listep2").addClass("active"); - $("#prgsecwiz").width('50%'); - $(".previous").show(); - - step++; - } + $('#imgProfileContainer').show(); + $("#dropzone").hide(); + $("#btnSaveProfile").hide(); + $("#btnCancelProfile").hide(); + $("#statusedit").hide(); + $("#imgreset").hide(); - }); - $(".previous").click(function () { - - if (step == 2) { - $("#step1").show(); - $("#step2").hide(); - $("#listep2").removeClass("active"); - $("#listep1").addClass("active"); - $("#prgsecwiz").width('25%'); - $(".previous").hide(); - $(".next").show(); - step--; - } + $("#btnEditProfile").bind('touchstart', function () { - if (step == 3) { - $("#step2").show(); - $("#step3").hide(); - $("#listep3").removeClass("active"); - $("#listep2").addClass("active"); - $("#prgsecwiz").width('50%'); - $(".previous").show(); - $(".next").show(); - step--; - } + key = ''; - if (step == 4) { - $("#step3").show(); - $("#step4").hide(); - $("#listep4").removeClass("active"); - $("#listep3").addClass("active"); - $("#prgsecwiz").width('75%'); - $(".previous").show(); - $(".next").hide(); - step--; - } + $('#imgProfileContainer').hide(); + $("#dropzone").show(); + $("#btnSaveProfile").show(); + $("#btnCancelProfile").show(); + $("#btnEditProfile").hide(); + $("#statusedit").show(); + $("#profnmests").hide(); + $("#imgreset").show(); + $("#txtStatusText").val(Engine.m_statusText); }); + $("#imgreset").bind('touchstart', function () { + Engine.m_profileImage = ""; + imgReset = true; + var imageSrc = "images/avatar/256px/Avatar-" + pad(Engine.m_nickname.length) + ".png"; + document.getElementById('imgProfile').src = imageSrc; + $('#imgProfileContainer').show(); + $('#dropzone').hide(); + $('progressNumber').text(''); + $("#imgreset").hide(); - - - - $("#btnReset2fa").click(function () { - - //stretch password - //download the recovery packet - //decrypt - //return shared secret - //no feedback apart from, please check your email - var fguid = $("#txtreset2faguid").val(); - var fusername = $("#txtreset2fausername").val(); - var fpwd = $("#txtreset2fapassword").val(); - - $("#reset2faerror").hide(); - $("#reset2fasuccess").hide(); - - Engine.ResetTwoFactor(fguid, fusername, fpwd, function (err, results) { - - if (err) { - $("#reset2faerror").show(); - $("#reset2faerrormessage").html('There was an error'); - } else { - $("#validate2fareset").show(); - $("#reset2fa").hide(); - } - }); - - }); - - - $("#btnhidekeys").click(function () { - $("#secdisphrase").hide(); - $("#secdisninki").hide(); - $("#btnhidekeys").hide(); - $("#btndisplaykeys").show(); }); - $("#btndisplaykeys").click(function () { - - //get the wallet packet - //secdisphrase - - var ninkiPub = Engine.m_walletinfo.ninkiPubKey; - var phrase = Engine.m_walletinfo.hotHash; - - var bip39 = new BIP39(); // 'en' is the default language - var hotmnem = bip39.entropyToMnemonic(phrase); + var imgReset = false; + $("#btnSaveProfile").bind('touchstart', function () { - $("#secdisphrase").html(hotmnem); - $("#secdisninki").html(ninkiPub); - $("#secdisphrase").show(); - $("#secdisninki").show(); - $("#btnhidekeys").show(); - $("#btndisplaykeys").hide(); + //updateUserProfile - }); + var statusText = $("#txtStatusText").val(); + if (key == '' && !imgReset) { + key = Engine.m_profileImage; + } - //depreciated - $("#btn2faResetValidate").click(function () { + Engine.updateUserProfile(key, statusText, Engine.m_invoiceTax, function (err, result) { - var vtoken = $("#txt2faResetToken").val(); + if (!err) { - Engine.EmailValidationForTwoFactor(vtoken, 0, function (err, response) { - if (err) { + var imageSrc = "images/avatar/256px/Avatar-" + pad(Engine.m_nickname.length) + ".png"; + var imageSrcSmall = "images/avatar/64px/Avatar-" + pad(Engine.m_nickname.length) + ".png"; - } else { + if (key != '' && !imgReset) { + imageSrc = "https://ninkip2p.imgix.net/" + key + "?crop=faces&fit=crop&h=256&w=256&mask=ellipse&border=1,d0d0d0"; + imageSrcSmall = "https://ninkip2p.imgix.net/" + key + "?crop=faces&fit=crop&h=64&w=64&mask=ellipse&border=1,d0d0d0"; + } - if (response != "Valid") { - $("#val2fatokenerror").show(); + $("#imgProfile").attr("src", imageSrc); + $("#imgtoprightprofile").attr("src", imageSrcSmall); - if (response == "Expired") { - $("#val2fatokenerrormessage").html('Your token has expired'); - } - if (response == "Invalid") { - $("#val2fatokenerrormessage").html('Your token is not valid'); - } + $('#imgProfileContainer').show(); + $("#dropzone").hide(); + $("#btnSaveProfile").hide(); + $("#btnCancelProfile").hide(); + $("#btnEditProfile").show(); + $("#statusedit").hide(); + $("#mystatus").text(statusText); + $("#txtStatusText").val(statusText); + $("#profnmests").show(); + $("#imgreset").hide(); + imgReset = false; + $("#profileimgfile").val(''); + $("#progressNumber").val(''); - } else { - $("#val2fatoken").hide(); - $("#val2fatokenerror").hide(); - location.reload(); - } } }); }); + $("#btnCancelProfile").bind('touchstart', function () { - //transaction filters - - $("#optDay").click(function () { - trasactionFilterOn = true; - currentTransactionFilter = 'Day'; - lastNoOfTrans = -1; - updateTransactions(); - }); - - $("#optWeek").click(function () { - trasactionFilterOn = true; - currentTransactionFilter = 'Week'; - lastNoOfTrans = -1; - updateTransactions(); - }); - - $("#optMonth").click(function () { - trasactionFilterOn = true; - currentTransactionFilter = 'Month'; - lastNoOfTrans = -1; - updateTransactions(); - }); - - $('#btntransearch').click(function () { - trasactionFilterOn = true; - currentTransactionFilter = 'Search'; - lastNoOfTrans = -1; - updateTransactions(); - }); - - $('#btntranclear').click(function () { - trasactionFilterOn = false; - currentTransactionFilter = ''; - lastNoOfTrans = -1; - updateTransactions(); - $("#optDay").removeClass('active'); - $("#optWeek").removeClass('active'); - $("#optMonth").removeClass('active'); - $("#txttransearch").val(''); - - }); - - - $('#thtrandate').click(function () { - - //reset contact widget - if (currentTransactionSort == 'ContactDesc') { - $('#thtrancontact').toggleClass('active'); - } - - if (currentTransactionSort == 'DateDesc') { - currentTransactionSort = 'DateAsc'; - } else { - currentTransactionSort = 'DateDesc'; - } - - trasactionSortOn = true; - lastNoOfTrans = -1; - updateTransactions(); - }); + $('#imgProfileContainer').show(); + $("#dropzone").hide(); + $("#btnSaveProfile").hide(); + $("#btnCancelProfile").hide(); + $("#btnEditProfile").show(); - $('#thtrancontact').click(function () { + //reset profile image - //reset date widget - if (currentTransactionSort == 'DateDesc') { - $('#thtrandate').toggleClass('active'); - } + var imageSrc = "images/avatar/256px/Avatar-" + pad(Engine.m_nickname.length) + ".png"; - if (currentTransactionSort == 'ContactAsc') { - currentTransactionSort = 'ContactDesc'; - } else { - currentTransactionSort = 'ContactAsc'; + if (Engine.m_profileImage != '') { + imageSrc = "https://ninkip2p.imgix.net/" + Engine.m_profileImage + "?crop=faces&fit=crop&h=256&w=256&mask=ellipse&border=1,d0d0d0"; } - trasactionSortOn = true; - lastNoOfTrans = -1; - updateTransactions(); - }); + $("#imgProfile").attr("src", imageSrc); - $('#tpagfirst').click(function () { - currentPageIndex = 0; - lastNoOfTrans = -1; - updateTransactions(); + $("#statusedit").hide(); + $("#profnmests").show(); + $("#imgreset").hide(); }); - $('#tpaglast').click(function () { - currentPageIndex = Math.floor((filteredTransactions.length / transactionsPerPage)); - lastNoOfTrans = -1; - updateTransactions(); - - }); + var obj = $("#dropzone"); - $('#tpagnext').click(function () { - if (currentPageIndex < Math.floor((filteredTransactions.length / transactionsPerPage))) { - currentPageIndex = currentPageIndex + 1; - lastNoOfTrans = -1; - updateTransactions(); - } + obj.click(function () { + $("#profileimgfile").click(); }); - $('#tpagprev').click(function () { - if (currentPageIndex > 0) { - currentPageIndex = currentPageIndex - 1; - lastNoOfTrans = -1; - updateTransactions(); - } - }); + $("#profileimgfile").change(function (e) { + var control = document.getElementById("profileimgfile"); + var files = control.files; + //alert(files[0]); + //We need to send dropped files to Server + handleFileUpload(files, obj); - //invoice filters - //for me - $("#optPending").click(function () { - invoiceFilterOn = true; - currentInvoiceFilter = 'Pending'; - lastInvoiceToPayCount = -1; - showInvoiceList(); }); - $("#optPaid").click(function () { - invoiceFilterOn = true; - currentInvoiceFilter = 'Paid'; - lastInvoiceToPayCount = -1; - showInvoiceList(); + obj.on('dragenter', function (e) { + e.stopPropagation(); + e.preventDefault(); + $(this).css('border', '2px solid #0B85A1'); }); - $("#optRejected").click(function () { - invoiceFilterOn = true; - currentInvoiceFilter = 'Rejected'; - lastInvoiceToPayCount = -1; - showInvoiceList(); + obj.on('dragover', function (e) { + e.stopPropagation(); + e.preventDefault(); }); - $("#optClearInvoice").click(function () { - invoiceFilterOn = false; - currentInvoiceFilter = ''; - lastInvoiceToPayCount = -1; - showInvoiceList(); - }); + obj.on('drop', function (e) { - $('#btnSearchInvForMe').click(function () { - currentForMeInvoicePageIndex = 0; - invoiceFilterOn = true; - currentInvoiceFilter = 'Search'; - lastInvoiceToPayCount = -1; - showInvoiceList(); + $(this).addClass("b-dashed"); + $(this).addClass("b-light"); + e.preventDefault(); + var files = e.originalEvent.dataTransfer.files; + //alert(files[0]); + //We need to send dropped files to Server + handleFileUpload(files, obj); }); - - - - //by me - //invoice filters - $("#optByMePending").click(function () { - invoiceByMeFilterOn = true; - currentByMeInvoiceFilter = 'Pending'; - lastInvoiceByUserCount = -1; - showInvoiceByUserList(); + $(document).on('dragenter', function (e) { + e.stopPropagation(); + e.preventDefault(); }); - $("#optByMePaid").click(function () { - invoiceByMeFilterOn = true; - currentByMeInvoiceFilter = 'Paid'; - lastInvoiceByUserCount = -1; - showInvoiceByUserList(); + $(document).on('dragover', function (e) { + e.stopPropagation(); + e.preventDefault(); + obj.css('border', '2px dotted #0B85A1'); }); - $("#optByMeRejected").click(function () { - invoiceByMeFilterOn = true; - currentByMeInvoiceFilter = 'Rejected'; - lastInvoiceByUserCount = -1; - showInvoiceByUserList(); + $(document).on('drop', function (e) { + e.stopPropagation(); + e.preventDefault(); }); - $("#optByMeClear").click(function () { - invoiceByMeFilterOn = false; - currentByMeInvoiceFilter = ''; - lastInvoiceByUserCount = -1; - showInvoiceByUserList(); - }); + var key = ''; + function handleFileUpload(files, obj) { - $('#btnSearchInvByMe').click(function () { - currentByMeInvoicePageIndex = 0; - invoiceByMeFilterOn = true; - currentByMeInvoiceFilter = 'Search'; - lastInvoiceByUserCount = -1; - showInvoiceByUserList(); - }); + if (files.length > 0) { + var file = files[0]; + var fd = new FormData(); - $('#ibmpagfirst').click(function () { - currentByMeInvoicePageIndex = 0; - lastInvoiceByMeNetCount = -1; - showInvoiceByUserList(); - }); + key = "images\/" + Engine.m_nickname + '_' + (new Date).getTime() - $('#ibmpaglast').click(function () { - currentByMeInvoicePageIndex = Math.floor((filteredByMeInvoices.length / invoicesByMePerPage)); - lastInvoiceByMeNetCount = -1; - showInvoiceByUserList(); - }); + Ninki.API.post("/api/1/u/createS3Policy", { test: 'test' }, function (err, result) { - $('#ibmpagnext').click(function () { - if (currentByMeInvoicePageIndex < Math.floor((filteredByMeInvoices.length / invoicesByMePerPage))) { - currentByMeInvoicePageIndex = currentByMeInvoicePageIndex + 1; - lastInvoiceByMeNetCount = -1; - showInvoiceByUserList(); - } - }); + var policy = JSON.parse(result); - $('#ibmpagprev').click(function () { - if (currentByMeInvoicePageIndex > 0) { - currentByMeInvoicePageIndex = currentByMeInvoicePageIndex - 1; - lastInvoiceByMeNetCount = -1; - showInvoiceByUserList(); - } - }); + fd.append('key', key); + fd.append('acl', 'public-read'); + fd.append('Content-Type', file.type); + fd.append('bucket', 'ninkip2pimgstore'); + fd.append('AWSAccessKeyId', 'AKIAINOU56ATQFS3CLFQ'); + fd.append('policy', policy.s3Policy); + fd.append('signature', policy.s3Signature); + fd.append("file", file); + //fd.append("success_action_redirect", "https://localhost:1111/ok"); - //for me + var xhr = new XMLHttpRequest(); - $('#ifmpagfirst').click(function () { - currentForMeInvoicePageIndex = 0; - lastInvoiceToPayCount = -1; - showInvoiceList(); - }); + xhr.upload.addEventListener("progress", uploadProgress, false); + xhr.addEventListener("load", uploadComplete, false); + xhr.addEventListener("error", uploadFailed, false); + xhr.addEventListener("abort", uploadCanceled, false); - $('#ifmpaglast').click(function () { - currentForMeInvoicePageIndex = Math.floor((filteredForMeInvoices.length / invoicesForMePerPage)); - lastInvoiceToPayCount = -1; - showInvoiceList(); - }); + xhr.open('POST', 'https://ninkip2pimgstore.s3-us-west-1.amazonaws.com/', true); //MUST BE LAST LINE BEFORE YOU SEND - $('#ifmpagnext').click(function () { - if (currentForMeInvoicePageIndex < Math.floor((filteredForMeInvoices.length / invoicesForMePerPage))) { - currentForMeInvoicePageIndex = currentForMeInvoicePageIndex + 1; - lastInvoiceToPayCount = -1; - showInvoiceList(); - } - }); + xhr.send(fd); - $('#ifmpagprev').click(function () { - if (currentForMeInvoicePageIndex > 0) { - currentForMeInvoicePageIndex = currentForMeInvoicePageIndex - 1; - lastInvoiceToPayCount = -1; - showInvoiceList(); + }); } - }); - - - - getCookie('ninki_reg', function (res) { - if (res.length > 0) { - - showOpenWalletStart(); - - } else { - - showCreateWalletStart(); - } - }) + } - $("#password").keypress(function (e) { - if (e.which == 13) { - $("#btnLogin").click(); - } - }); - $("#twoFactorCode").keypress(function (e) { - if (e.which == 13) { - $("#btn2faLogin").click(); + function uploadProgress(evt) { + if (evt.lengthComputable) { + var percentComplete = Math.round(evt.loaded * 100 / evt.total); + document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%'; } - }); - - $("#password1").keypress(function (e) { - if (e.which == 13) { - $("#btnCreate").click(); + else { + document.getElementById('progressNumber').innerHTML = 'unable to compute'; } - }); - - - $("#cpassword").blur(function () { - $(".popover.fade.bottom.in").hide(); - }); - - $("#cpassword").focus(function () { - $(".popover.fade.bottom.in").show(); - }); - - $("#newpassword1").blur(function () { - $(".popover.fade.bottom.in").hide(); - }); - - $("#newpassword1").focus(function () { - $(".popover.fade.bottom.in").show(); - }); - - //$("#balance").html("... BTC"); - - $("#mainWallet").hide(); - $('#message').hide(); - $("#openwalletalert").hide(); - $("#createwalletalert").hide(); - $("#imgopenwaiting").hide(); - $("#imgcreatewaiting").hide(); - $("#showPhrases").hide(); - $("#twoFactorQr").hide(); - $("#2factor1").hide(); - $("#securitywizard").hide(); - $("#secdisphrase").hide(); - $("#secdisninki").hide(); - $("#btnhidekeys").hide(); - - $("#btnSendToFriend").hammer(null).bind("tap", function () { - - - sendMoney(SELECTEDFRIEND, 0); - - - }); - $("#sendfriendprog").hide(); - - $("#hforgotguid").click(function () { - - $("#createWalletStart").hide(); - $("#openWalletStart").hide(); - $("#lostguid").show(); - $("#reset2fa").hide(); - }); - - - $("#hlost2fa").click(function () { - - $("#createWalletStart").hide(); - $("#openWalletStart").hide(); - $("#lostguid").hide(); - $("#reset2fa").show(); - - }); - - - $("#emailresend").click(function () { - - Engine.sendWelcomeDetails(function (err, result) { - - if (!err) { - - $("#emailresendmessage").show(); - $("#emailresend").hide(); - //email has been resent, please check your email - } - - }); - - }); - - - $("#cpassword").on('change keyup', function () { - - $("#password1").parsley("validate"); - - }); - - - $("#twoFactorCodeCheck").on('change keyup', function () { - - $("#phraseloginerror").fadeOut(100); - - }); - - - $("#btnChangePassword").click(function () { - - $("#chngpwssuc").hide(); - $("#chngpwerr").hide(); - $("#chngpwdprog").hide(); - $("#chngpwdprogbar").width('0%'); - - var newpassword = $("#newpassword1").val(); - var oldpassword = $("#oldpwd").val(); - var twoFactorCode = $("#txtTwoFactorCodeForChangePwd").val(); - - if ($("#frmpwdchange").parsley('validate')) { - - $("#chngpwdprog").show(); - $("#chngpwdprogmess").show(); - $("#chngpwdprogbar").width('10%'); - $("#chngpwdprogmess").html('Getting packet...'); - - - if (oldpassword != newpassword) { - - //check password strength - if (($(".newpwstrength_viewport_progress .password-verdict").html() == 'Strong' || $(".newpwstrength_viewport_progress .password-verdict").html() == 'Very Strong')) { + } - //stretch old password - //verify that it matches the current one - $("#chngpwdprogbar").width('20%'); - $("#chngpwdprogmess").html('Getting details...'); + function uploadComplete(evt) { + /* This event is raised when the server send back a response */ + //alert("Done - " + evt.target.responseText); + document.getElementById('imgProfile').src = 'https://ninkip2p.imgix.net/' + key + "?fit=crop&crop=faces&h=128&w=128&mask=ellipse&border=1,d0d0d0"; + $('#imgProfileContainer').show(); + $('#dropzone').hide(); + $('progressNumber').text(''); + $("#imgreset").hide(); - setTimeout(function () { + } - Engine.ChangePassword(twoFactorCode, oldpassword, newpassword, "#chngpwdprogbar", "#chngpwdprogmess", function (err, results) { + function uploadFailed(evt) { + alert("There was an error attempting to upload the file." + evt); + } - if (err) { - $("#chngpwerr").show(); - $("#chngpwerrmess").html(results); - $("#chngpwdprogmess").hide(); - $("#chngpwdprog").hide(); + function uploadCanceled(evt) { + alert("The upload has been canceled by the user or the browser dropped the connection."); + } - } else { + }); - password = results; - $("#chngpwerr").hide(); - $("#chngpwdprogbar").width('100%'); - $("#chngpwdprog").hide(); - $("#chngpwdprogmess").hide(); - $("#chngpwdprogbar").hide(); - $("#chngpwssuc").show(); - $("#newpassword1").val(''); - $("#newpassword2").val(''); - $("#oldpwd").val(''); - $("#txtTwoFactorCodeForChangePwd").val(''); - } + $(document).ready(function () { - }); + $("#pairdeviceblob").change(function () { - }, 500); - } + $("#loginpin").hide(); + $("#pairstep1").hide(); + $("#pairstep2").show(); - } else { - $("#chngpwerr").show(); - $("#chngpwerrmess").html("Passwords are the same. Password not updated"); - $("#chngpwdprogmess").hide(); - $("#chngpwdprog").hide(); - } - } }); - $("#btnVerify").click(function () { - - var code = $("#txtCode").val(); - - $("#txtCode").css("border-color", "#ccc"); - $("#validatefail").hide(); - $("#validatesuccess").hide(); - - var bip39 = new BIP39(); - code = bip39.mnemonicToHex(code); - - if (code.length != 40) { - $("#txtCode").css("border-color", "#ffaaaa"); - return; - } - - //get the hash to validate against - //this will confirm that my friend has the same keys - //i orginally packaged for him - - Engine.verifyFriendData(SELECTEDFRIEND, code, function (err, result) { - - if (result) { - $("#validateform").hide(); - $("#validatesuccess").show(); - $("#txtCode").val(''); - selectedFriend.validated = true; - FRIENDSLIST[selectedFriend.userName].validated = true; - updateSelectedFriend(); - - //update list also + $("#btnUnpair").click(function () { - //find friend in list and update the validated icon - $("#myfriends #seltarget" + selectedFriend.userName).html('
Date: '; - popcontent += trdate; - popcontent += '
'; + var trdate = new Date(tran.TransDateTime.match(/\d+/)[0] * 1); - popcontent += 'TransactionId
'; - popcontent += ''; - popcontent += transactions[i].TransactionId; - popcontent += '
'; + var timeLabel = prettydate.format(trdate); - popcontent += 'Address: '; - popcontent += transactions[i].Address; - popcontent += '
'; + $(elem).html(timeLabel); - popcontent += 'Amount: '; - popcontent += convertFromSatoshis(transactions[i].Amount, COINUNIT) + ' '; - popcontent += COINUNIT + '
'; + console.log('updating 2'); - popcontent += 'Send/Receive: '; - popcontent += transactions[i].TransType; - popcontent += '
'; + }); - $("#btnpop" + i).popover({ - placement: 'left', // top, bottom, left or right - title: 'Transaction Details', - html: 'true', - content: '