From aaa71d13f042bcdfa8a1e135abd7095aa84b99c0 Mon Sep 17 00:00:00 2001 From: Administrator Date: Sun, 8 Mar 2015 13:25:27 +0900 Subject: [PATCH] Release 0.1.7 mobile Apps --- src/ninki-api.js | 84 +- src/ninki-device.js | 133 ++ src/ninki-engine.js | 296 ++- src/ninki-ui-mobile.js | 4358 ++++++++++++++++++++++++++++------------ src/ninki-ui.js | 7 +- 5 files changed, 3529 insertions(+), 1349 deletions(-) diff --git a/src/ninki-api.js b/src/ninki-api.js index 41b9689..ff64747 100644 --- a/src/ninki-api.js +++ b/src/ninki-api.js @@ -133,8 +133,6 @@ function lpost(url, postData, callback) { req.end(); - - } else { $.ajax({ @@ -205,10 +203,10 @@ function lpost(url, postData, callback) { } //return callback(true, data.statusText); } else { - location.reload(); + //location.reload(); } } else { - + return callback(true, sanitizer.sanitize(data.statusText)); } @@ -573,6 +571,41 @@ API.getTransactionRecords = function (guid, sharedid, callback) { }; +API.getTransactionFeed = function (guid, sharedid, callback) { + + var postData = { guid: guid, sharedid: sharedid }; + + lpost("/api/1/u/gettransactionfeed", postData, function (err, transactions) { + + if (!err) { + var jtran = JSON.parse(transactions); + return callback(err, jtran); + } else { + return callback(err, transactions); + } + + }); + +}; + +API.getTransactionsForNetwork = function (guid, sharedid, username, callback) { + + var postData = { guid: guid, sharedid: sharedid, username: username }; + + lpost("/api/1/u/gettransactionsfornetwork", postData, function (err, transactions) { + + if (!err) { + var jtran = JSON.parse(transactions); + return callback(err, jtran); + } else { + return callback(err, transactions); + } + + }); + +}; + + API.getInvoiceList = function (guid, sharedid, callback) { var postData = { guid: guid, sharedid: sharedid }; @@ -591,6 +624,24 @@ API.getInvoiceList = function (guid, sharedid, callback) { }; +API.getInvoicesToPayNetwork = function (guid, sharedid, username, callback) { + + var postData = { guid: guid, sharedid: sharedid, username: username }; + + lpost("/api/1/u/getinvoicestopaynetwork", postData, function (err, invoices) { + + if (!err) { + var jtran = JSON.parse(invoices); + + return callback(err, jtran); + } else { + return callback(err, invoices); + } + + }); + +}; + API.getInvoiceByUserList = function (guid, sharedid, callback) { var postData = { guid: guid, sharedid: sharedid }; @@ -608,6 +659,23 @@ API.getInvoiceByUserList = function (guid, sharedid, callback) { }; +API.getInvoicesByUserNetwork = function (guid, sharedid, username, callback) { + + var postData = { guid: guid, sharedid: sharedid, username: username }; + + lpost("/api/1/u/getinvoicesbyusernetwork", postData, function (err, invoices) { + + if (!err) { + var jtran = JSON.parse(invoices); + return callback(err, jtran); + } else { + return callback(err, invoices); + } + + }); + +}; + API.updateInvoice = function (guid, sharedid, username, invoiceId, transactionId, status, callback) { @@ -681,6 +749,14 @@ API.getDeviceToken = function (guid, sharedid, deviceName, twoFactorCode, callba }); }; +API.getDeviceTokenForApp = function (guid, sharedid, deviceName, callback) { + var postData = { guid: guid, sharedid: sharedid, deviceName: deviceName}; + return lpost("/api/1/u/getdevicetokenforapp", postData, function (err, dataStr) { + return callback(err, dataStr); + }); +}; + + API.getRecoveryPacket = function (guid, callback) { diff --git a/src/ninki-device.js b/src/ninki-device.js index 9ea57d5..cbadec8 100644 --- a/src/ninki-device.js +++ b/src/ninki-device.js @@ -179,6 +179,139 @@ function Device() { } } + + + + this.setSecureStorageObject = setSecureStorageObject; + function setSecureStorageObject(cname, cvalue, key, encryptor, expiry) { + + + if (isChromeApp()) { + + var encp = encryptor(cvalue, key); + var ptok = {}; + ptok.ct = encp.toString(); + ptok.iv = encp.iv.toString(); + + if (expiry) { + ptok.date = new Date(); + ptok.expiry = expiry; + } + + var ptoken = JSON.stringify(ptok); + + var obj = {}; + obj[cname] = ptoken + + chrome.storage.local.set(obj, function () { + + console.log("saved"); + + }); + + } + else { + + var encp = encryptor(cvalue, key); + var ptok = {}; + ptok.ct = encp.toString(); + ptok.iv = encp.iv.toString(); + + if (expiry) { + ptok.date = new Date(); + ptok.expiry = expiry; + } + + var ptoken = JSON.stringify(ptok); + localStorage.setItem(cname, ptoken); + + } + + + } + + + this.getSecureStorageObject = getSecureStorageObject; + function getSecureStorageObject(cname, key, decryptor, callback) { + + if (isChromeApp()) { + + chrome.storage.local.get(cname, function (result) { + + result = result[cname]; + + if (result != "") { + var decryptok = true; + var datac = ""; + try { + + var enc = JSON.parse(result); + + if (enc.date) { + if (enc.expiry) { + var currentdate = new Date(); + if (((new Date) - new Date(enc.date)) < enc.expiry) { + datac = decryptor(enc.ct, key, enc.iv); + } + } + } else { + datac = decryptor(enc.ct, key, enc.iv); + } + + } catch (error) { + decryptok = false; + } + + } + + return callback(result); + + }); + + } else { + + if (localStorage.getItem(cname)) { + + result = localStorage.getItem(cname); + + if (result != "") { + var decryptok = true; + var datac = ""; + try { + var enc = JSON.parse(result); + + if (enc.date) { + if (enc.expiry) { + var currentdate = new Date(); + if (((new Date) - new Date(enc.date)) < enc.expiry) { + datac = decryptor(enc.ct, key, enc.iv); + } + } + } else { + datac = decryptor(enc.ct, key, enc.iv); + } + + } catch (error) { + decryptok = false; + } + + if (decryptok) { + result = datac; + } + + } + + return callback(result); + + } else { + return callback(''); + } + + } + + } + + } module.exports = Device; diff --git a/src/ninki-engine.js b/src/ninki-engine.js index 2cf892a..a3e8efd 100644 --- a/src/ninki-engine.js +++ b/src/ninki-engine.js @@ -31,6 +31,8 @@ function Engine() { this.m_invoiceTax = 0.1; this.m_privKey = ''; this.m_pubKey = ''; + this.m_privKeyRaw = ''; + this.m_pubKeyRaw = ''; this.m_APIToken = ''; this.m_appInitialised = false; this.m_watchOnly = false; @@ -52,6 +54,55 @@ function Engine() { } + this.serialize = serialize; + function serialize() { + + var serTarget = {}; + serTarget.m_walletinfo = m_this.m_walletinfo; + serTarget.m_sharedid = m_this.m_sharedid; + serTarget.m_twoFactorOnLogin = m_this.m_twoFactorOnLogin; + serTarget.m_nickname = m_this.m_nickname; + //serTarget.m_profileImage = m_this.m_profileImage; + //serTarget.m_statusText = m_this.m_statusText; + serTarget.m_guid = m_this.m_guid; + //serTarget.m_settings = m_this.m_settings; + serTarget.m_fingerprint = m_this.m_fingerprint; + //serTarget.m_secret = m_this.m_secret; + serTarget.m_invoiceTax = m_this.m_invoiceTax; + + serTarget.m_privKeyRaw = m_this.m_privKeyRaw; + serTarget.m_pubKeyRaw = m_this.m_pubKeyRaw; + + return JSON.stringify(serTarget); + + } + + this.initialize = initialize; + function initialize(cache) { + + m_this.m_walletinfo = cache.m_walletinfo; + m_this.m_sharedid = cache.m_sharedid; + m_this.m_twoFactorOnLogin = cache.m_twoFactorOnLogin; + m_this.m_nickname = cache.m_nickname; + //m_this.m_profileImage = cache.m_profileImage; + //m_this.m_statusText = cache.m_statusText; + m_this.m_guid = cache.m_guid; + //m_this.m_settings = cache.m_settings; + m_this.m_fingerprint = cache.m_fingerprint; + //m_this.m_secret = cache.m_secret; + m_this.m_invoiceTax = cache.m_invoiceTax; + + var privKeys = openpgp.key.readArmored(cache.m_privKeyRaw); + var publicKeys = openpgp.key.readArmored(cache.m_pubKeyRaw); + + if (privKeys.keys[0].decrypt(m_this.m_sharedid)) { + m_this.m_privKey = privKeys.keys[0]; + } + + m_this.m_pubKey = publicKeys.keys[0]; + + cache = {}; + } this.appHasLoaded = appHasLoaded; function appHasLoaded() { @@ -94,6 +145,8 @@ function Engine() { var rng = new Uint8Array(b); if (typeof window === 'undefined') { + //this is to support the test scripts + //which are executed using node.js try { var buf = crypto.randomBytes(256); @@ -381,11 +434,17 @@ function Engine() { m_this.Device.getStorageItem("ninki_rem", function (tft) { - var jtft = JSON.parse(tft); + if (tft != "") { + var jtft = JSON.parse(tft); - var fatoken = decryptNp(jtft.ct, key, jtft.iv); + var fatoken = decryptNp(jtft.ct, key, jtft.iv); - return callback(false, hothash, fatoken); + return callback(false, hothash, fatoken); + } else { + + return callback(false, hothash, ""); + + } }); @@ -431,8 +490,21 @@ function Engine() { var encHotHash = encryptNp(hotHash, m_this.m_password); - m_this.Device.setStorageItem('hk' + m_this.m_guid, encHotHash.toString()); - m_this.Device.setStorageItem('hkiv' + m_this.m_guid, encHotHash.iv.toString()); + if (m_this.Device.isChromeApp() || m_this.Device.isBrowser() || m_this.Device.isNode()) { + + m_this.Device.setStorageItem('hk' + m_this.m_guid, encHotHash.toString()); + m_this.Device.setStorageItem('hkiv' + m_this.m_guid, encHotHash.iv.toString()); + + } else { + + var htok = {}; + htok.ct = encHotHash.toString(); + htok.iv = encHotHash.iv.toString(); + var hkey = JSON.stringify(htok); + + m_this.Device.setStorageItem('ninki_h', hkey); + + } callback(false, "ok"); @@ -461,7 +533,7 @@ function Engine() { //create wallet //create a new wallet and save to the server this.createWallet = createWallet; - function createWallet(guid, password, username, emailAddress, callback) { + function createWallet(guid, password, username, emailAddress, callback, progress) { m_this.m_oguid = guid; @@ -488,11 +560,12 @@ function Engine() { } else { - //$('#textMessageCreate').text('stretching password...'); - setTimeout(function () { + progress('stretching password...'); + setTimeout(function () { + //stretch the password with the local guid as a salt m_this.m_password = pbkdf2(password, m_this.m_oguid); @@ -522,11 +595,10 @@ function Engine() { walletInformation.wallet.recPacketIV = recpacket.iv.toString(); //save the wallet to the server - //$('#textMessageCreate').text('saving data...'); + progress('saving data...'); setTimeout(function () { - API.post("/api/1/u/createaccount2", walletInformation.wallet, function (err, response) { if (err) { @@ -534,15 +606,21 @@ function Engine() { return callback(err, "ErrSavePacket"); } else { + + //set the session + API.registerToken(response); + m_this.m_APIToken = response; + //pass back the wallet and info to the calling function return callback(false, walletInformation); } }); + }, 50); } - }); + }, progress); }, 50); } @@ -554,14 +632,15 @@ function Engine() { //function makeNewWallet //this function calls the server which generates the Ninki key pair to be used for the wallet //the server returns the public key to the client so that it can be saved in the user's encrypted packet - function makeNewWallet(nickname, email, callback) { + function makeNewWallet(nickname, email, callback, progress) { //TODO add some more param checking //rename this function setTimeout(function () { - //$('#textMessageCreate').text('creating account...'); + + progress('creating account...'); API.getMasterPublicKeyFromUpstreamServer(m_this.m_oguid, function (err, ninkiPubKey, userToken, secret) { if (err) { @@ -573,24 +652,24 @@ function Engine() { } else { return callback(err, walletInformation, userToken); } - }); + }, progress); } }); }, 50); } - function makeNewWalletPacket(nickname, emailAddress, ninkiPubKey, userToken, secret, callback) { + function makeNewWalletPacket(nickname, emailAddress, ninkiPubKey, userToken, secret, callback, progress) { - //$('#textMessageCreate').text('getting entropy...'); + progress('getting entropy...'); setTimeout(function () { //what to do if running in node // crypto provider module - var rngcold = getRandomValues(32); + var rngcold = getRandomValues(16); var coldKeyBytes = []; for (var i = 0; i < rngcold.length; ++i) { @@ -598,40 +677,31 @@ function Engine() { } //get some random data for the hot key - var rnghot = getRandomValues(32); + var rnghot = getRandomValues(16); var hotKeyBytes = []; for (var i = 0; i < rnghot.length; ++i) { hotKeyBytes[i] = rnghot[i]; } - var bip39 = new BIP39(); // 'en' is the default language - var hotmnem = bip39.entropyToMnemonic(rnghot); - var coldmnem = bip39.entropyToMnemonic(rngcold); - - //var seedtest = bip39.mnemonicToSeed(hotmnem, ''); - - //$('#textMessageCreate').text('creating cold keys...'); + progress('creating cold keys...'); setTimeout(function () { - //hash the random data to generate the seed for the cold key space - //Cold key space - var coldHash = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(coldKeyBytes)).toString(); + + var coldHash = Bitcoin.convert.bytesToHex(coldKeyBytes); var coldWallet = Bitcoin.HDWallet.fromSeedHex(coldHash, m_this.m_network); //get the keys as strings var coldPriv = coldWallet.toString(" "); var coldPub = coldWallet.toString(); - //$('#textMessageCreate').text('creating hot keys...'); - + progress('creating hot keys...'); setTimeout(function () { - //hash the random data to generate the seed for the hot key space - //Hot key space - var hotHash = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(hotKeyBytes)).toString(); + + var hotHash = Bitcoin.convert.bytesToHex(hotKeyBytes); var hotWallet = Bitcoin.HDWallet.fromSeedHex(hotHash, m_this.m_network); //get the keys as strings @@ -647,7 +717,7 @@ function Engine() { var hcbkey = Bitcoin.convert.hexToBytes(hckey); var hchkey = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(hcbkey)).toString(); - //$('#textMessageCreate').text('creating pgp keys...'); + progress('creating pgp keys...'); setTimeout(function () { @@ -735,6 +805,7 @@ function Engine() { saveHotHash(hotHash, function (err, res) { + var bip39 = new BIP39(); var walletInformation = { wallet: wallet, coldWalletPhrase: bip39.entropyToMnemonic(coldHash), @@ -743,7 +814,6 @@ function Engine() { hckey: hchkey }; - return callback(err, walletInformation); @@ -1246,6 +1316,10 @@ function Engine() { var publicKeys = openpgp.key.readArmored(rsaKeyPair.RSAPub); var privKeys = openpgp.key.readArmored(rsaKeyPair.RSAPriv); + + m_this.m_pubKeyRaw = rsaKeyPair.RSAPub; + m_this.m_privKeyRaw = rsaKeyPair.RSAPriv; + m_this.m_privKey = privKeys.keys[0]; m_this.m_pubKey = publicKeys.keys[0]; @@ -1476,7 +1550,7 @@ function Engine() { corNodesToProcess = nodes.length; cordovaDeriveKey(mpk, nodes, mkpder, function (result) { - + return cdcallback(mkpder); @@ -1498,7 +1572,7 @@ function Engine() { if (corNodesDone == corNodesToProcess) { - + return derfinished(mkpder) } else { @@ -1519,8 +1593,8 @@ function Engine() { }, function errorHandler(err) { - - + + }, 'ECPlugin', 'cordovaECDerKey', @@ -1675,7 +1749,7 @@ function Engine() { } - + //call to cordova plugin for private key derivation @@ -1706,20 +1780,20 @@ function Engine() { //if we are sending money to a contact or paying an invoice //we need to derive addresses on their behalf - + deriveKeys(bipHot, nodeLevels, function (ret) { if (m_this.Device.isiOS()) { - + for (var i = 0; i < ret.length; i++) { - + var nkey = new Bitcoin.ECKey(ret[i]); - + userHotPrivKeys.push(nkey); - + } } else { @@ -1728,7 +1802,7 @@ function Engine() { } - + if (sendType == 'friend' || sendType == 'invoice') { @@ -1742,7 +1816,7 @@ function Engine() { //generate the address for the contact //this must be done on the client - + statuscallback('creating address...', '30%'); createAddressForFriend(friendUserName, function (err, address) { @@ -1755,12 +1829,12 @@ function Engine() { //create the change address, this must be done on the client statuscallback('Creating change address...', '40%'); - + createAddress('m/0/1', changeAmount, function (err, changeaddress) { if (!err) { - + if (changeAmount > 0) { addressToSend.push(changeaddress); } @@ -2113,7 +2187,7 @@ function Engine() { function callback(data) { hcoldKey = data; - + coldKey = Bitcoin.convert.hexToBytes(data); @@ -2122,7 +2196,7 @@ function Engine() { hninkiKey = data; - + ninkiKey = Bitcoin.convert.hexToBytes(data); @@ -2152,7 +2226,7 @@ function Engine() { pk3: hninkiKey }; API.post("/api/1/u/createaddress", postData, function (err, result) { - + if (!err) { return cacallback(err, address); } else { @@ -2198,13 +2272,13 @@ function Engine() { var bipCold = Bitcoin.HDWallet.fromBase58(m_this.m_walletinfo.coldPub); var bipNinki = Bitcoin.HDWallet.fromBase58(m_this.m_walletinfo.ninkiPubKey); - + var hotKey = deriveChild(path, bipHot); - + var coldKey = deriveChild(path, bipCold); - + var ninkiKey = deriveChild(path, bipNinki); - + //now create the multisig address var script = [0x52]; @@ -2307,7 +2381,7 @@ function Engine() { function callback(data) { hhotKey = data; - + hotKey = Bitcoin.convert.hexToBytes(data); @@ -2729,23 +2803,23 @@ function Engine() { //if (!err) { - if (!result) { - - m_this.createFriend(username, '', function (err, result) { + if (!result) { - if (err) { + m_this.createFriend(username, '', function (err, result) { - return callback(err, result); - } else { + if (err) { - return callback(err, result); - } - }); + return callback(err, result); + } else { - } else { + return callback(err, result); + } + }); - return callback(err, result); - } + } else { + + return callback(err, result); + } //} else { // return callback(err, result); //} @@ -2761,8 +2835,11 @@ function Engine() { this.acceptFriendRequest = acceptFriendRequest; - function acceptFriendRequest(username, callback) { + function acceptFriendRequest(username, callback, progress) { + if (progress) { + progress("Getting request.."); + } var postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: username }; API.post("/api/1/u/getfriendrequestpacket", postData, function (err, packet) { @@ -2770,6 +2847,11 @@ function Engine() { //get the packet from friend containing the public key set to //be used for address generation + + if (progress) { + progress("Encrypting data..."); + } + var message = packet; var rsaKey = ''; @@ -2805,6 +2887,11 @@ function Engine() { validated: false }; + if (progress) { + progress("Signing data..."); + } + + var encrypted = openpgp.signAndEncryptMessage([m_this.m_pubKey], m_this.m_privKey, JSON.stringify(packet)); postData = { @@ -2836,11 +2923,14 @@ function Engine() { } this.verifyFriendData = verifyFriendData; - function verifyFriendData(username, code, callback) { + function verifyFriendData(username, code, callback, progress) { //update packet with status as verified and log //the verification code + if (progress) { + progress("Getting packet..."); + } var postData = { guid: m_this.m_guid, sharedid: m_this.m_sharedid, username: username }; API.post("/api/1/u/getfriendpacket", postData, function (err, packet) { @@ -2860,6 +2950,11 @@ function Engine() { if (code == pubKeyUsed.primaryKey.fingerprint) { + + if (progress) { + progress("Verifying..."); + } + var reencrypt = { hotPub: payload.hotPub, coldPub: payload.coldPub, @@ -2878,6 +2973,11 @@ function Engine() { validationHash: code }; + + if (progress) { + progress("Updating..."); + } + API.post("/api/1/u/updatefriend", postData, function (err, result) { return callback(err, result); @@ -3065,7 +3165,11 @@ function Engine() { API.post("/api/1/u/updatetwofactor", postData, function (err, result) { - API.registerToken(result); + if (!err) { + + API.registerToken(result); + + } callback(err, result); @@ -3319,7 +3423,7 @@ function Engine() { ctok.ct = tfso.toString(); ctok.iv = tfso.iv.toString(); m_this.Device.setStorageItem("tfso" + m_this.m_guid, JSON.stringify(ctok)); - + } m_this.m_password = newpassword; @@ -3887,6 +3991,19 @@ function Engine() { }); } + this.doesEmailExist = doesEmailExist; + function doesEmailExist(email, callback) { + API.doesAccountExist('', email, function (err, accExists) { + + if (err) { + callback(err, accExists); + } else { + callback(err, accExists.EmailExists); + } + + }); + } + this.sendWelcomeDetails = sendWelcomeDetails; function sendWelcomeDetails(callback) { API.sendWelcomeDetails(m_this.m_guid, m_this.m_sharedid, callback); @@ -4007,6 +4124,18 @@ function Engine() { API.getTransactionRecords(m_this.m_guid, m_this.m_sharedid, callback); } + this.getTransactionFeed = getTransactionFeed; + function getTransactionFeed(callback) { + API.getTransactionFeed(m_this.m_guid, m_this.m_sharedid, callback); + } + + this.getTransactionsForNetwork = getTransactionsForNetwork; + function getTransactionsForNetwork(username, callback) { + API.getTransactionsForNetwork(m_this.m_guid, m_this.m_sharedid, username, callback); + } + + + this.getInvoiceList = getInvoiceList; function getInvoiceList(callback) { API.getInvoiceList(m_this.m_guid, m_this.m_sharedid, callback); @@ -4017,6 +4146,18 @@ function Engine() { API.getInvoiceByUserList(m_this.m_guid, m_this.m_sharedid, callback); } + + this.getInvoicesToPayNetwork = getInvoicesToPayNetwork; + function getInvoicesToPayNetwork(username, callback) { + API.getInvoicesToPayNetwork(m_this.m_guid, m_this.m_sharedid, username, callback); + } + + this.getInvoicesByUserNetwork = getInvoicesByUserNetwork; + function getInvoicesByUserNetwork(username, callback) { + API.getInvoicesByUserNetwork(m_this.m_guid, m_this.m_sharedid, username, callback); + } + + this.updateInvoice = updateInvoice; function updateInvoice(username, invoiceId, transactionId, status, callback) { API.updateInvoice(m_this.m_guid, m_this.m_sharedid, username, invoiceId, transactionId, status, callback); @@ -4065,7 +4206,7 @@ function Engine() { callback(err, jekey); } - + } else { @@ -4125,6 +4266,11 @@ function Engine() { API.getDeviceToken(m_this.m_guid, m_this.m_sharedid, deviceName, twoFactorCode, callback); } + this.getDeviceTokenForApp = getDeviceTokenForApp; + function getDeviceTokenForApp(deviceName, callback) { + API.getDeviceTokenForApp(m_this.m_guid, m_this.m_sharedid, deviceName, callback); + } + this.getLimitStatus = getLimitStatus; function getLimitStatus(callback) { API.getLimitStatus(m_this.m_guid, m_this.m_sharedid, function (err, res) { @@ -4166,7 +4312,7 @@ function Engine() { if (res == "") { - return callback(false,""); + return callback(false, ""); } diff --git a/src/ninki-ui-mobile.js b/src/ninki-ui-mobile.js index a967cee..83195b5 100644 --- a/src/ninki-ui-mobile.js +++ b/src/ninki-ui-mobile.js @@ -1,4 +1,4 @@ -//Nini Wallet +//Ninki Wallet //Mobile UI @@ -6,11 +6,8 @@ var Bitcoin = require('bitcoinjs-lib'); var BIP39 = require('./bip39'); var prettydate = require("pretty-date"); - function UI() { - - var Engine = new Ninki.Engine(); @@ -53,6 +50,7 @@ function UI() { var contactPhraseCache = {}; var isPairing = false; + var isCreate = false; var ua = window.navigator.userAgent; @@ -61,6 +59,83 @@ function UI() { var pintaps = 0; var prevpin = ''; + var ONE_HOUR = 60 * 60 * 1000; + + window.isSessionLive = function (callback) { + + Ninki.API.getPrice(Engine.m_guid, Engine.m_settings.LocalCurrency, function (err, result) { + + if (!err) { + return callback(true); + } else { + return callback(false); + } + + }); + + } + + + + window.showLoginPIN = function () { + + + + if ($("#isactive").val() == 1) { + + if ($(".footer").is(":visible")) { + + $("#footermode").val(1); + + } else { + + $("#footermode").val(0); + + } + + } + + + if (window.cordova) { + cordova.plugins.Keyboard.close(); + } + + $("#isactive").val(0); + + + + window.resetPin(); + + + + $("#paddel").hide(); + + $('.numdone').attr("style", "background-color:white"); + + $("#loginpinno").val(''); + + $("#pinloginmessage").text("Enter your PIN number"); + + + + $("#pinimage").show(); + + $("#pinpair").hide(); + + $("#pinrepeat").hide(); + + + + $("#loginpin").show(); + + $("#nonlogin").hide(); + + + + $(".footer").hide(); + + } + if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) { @@ -142,1164 +217,1053 @@ function UI() { } + var profilepagestate = ''; + var networkpagestate = ''; + var friendpagestate = ''; + var menustate = ''; + var cl = ''; - //loginPIN - //this function takes the user's input PIN number - //and authenticates the user - //if the user has not previosuly authenticated it downloads and decrypts - //all the relevant wallet data - var pinlock = false; - function loginPIN() { + var scrolling = false; + var scrollingnettran = false; + var scrollingnetlist = false; + jQuery(document).ready(function () { - var pin = $("#loginpinno").val(); + var $body = jQuery('body'); - $("#enterpinalert").hide(); - if (pin.length == 4 && !pinlock) { + $("#dashboard").on("scroll", function () { + scrolling = true; + }); - pinlock = true; + $("#dashboard").on("touchstart", function () { - Engine.Device.getStorageItem("guid", function (guid) { + scrolling = false; + }); - if (!Engine.m_appInitialised) { + $("#pnlfriend").on("scroll", function () { + scrollingnettran = true; + }); - Engine.m_oguid = guid; + $("#pnlfriend").on("touchstart", function () { - var bytes = []; - for (var i = 0; i < guid.length; ++i) { - bytes.push(guid.charCodeAt(i)); - } + scrollingnettran = false; - Engine.m_guid = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(bytes)).toString(); - } + }); - Engine.getDeviceKey(pin, function (err, ekeyv) { + $("#networklist").on("scroll", function () { + scrollingnetlist = true; + }); - //decrypt the passcode - //if no error the PIN is valid - if (!err) { + $("#networklist").on("touchstart", function () { - if (!(typeof window.app === 'undefined')) { - app.isScanning = true; - } + scrollingnetlist = false; - //is the app previosuly intialised - - if (Engine.m_appInitialised) { + }); - //if so simply change the UI state - //a session with the server has been established - $('.numdone').attr("style", "background-color:white"); + bootbox.setDefaults({ 'backdrop': false, 'animate': true }); - //check state and display correct headers + //guid + //ninki_reg + //if device is paired then - $("#paddel").hide(); - $('.numdone').attr("style", "background-color:white"); - $("#loginpin").hide(); - $("#pinloginmessage").text("Enter your PIN number"); - $("#nonlogin").show(); + Engine.Device.getStorageItem("ninki_reg", function (reg) { - $("#loginpinno").val(''); - pinlock = false; + if (reg) { + isPairing = false; + $("#loginpin").show(); + $("#pinimage").show(); - //do we show the footer or not? + } else { + isPairing = true; + $("#pairDevice").show(); + $("#pinpair").show(); + } - if ($("#footermode").val() == 1) { - $(".footer").show(); - } else { - $(".footer").hide(); - } + }); - //double check footer - //bug workaround - if (menustate == "profile" && profilepagestate == "") { - $(".footer").show(); + //create wallet area - } - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } + Engine.fillElementWithGuid($("#createWalletStart input#guid")); - $("#isactive").val(1); + //$('#nickname').val($('#guid').val().substring(0, 7)); + //$('#emailaddress').val($('#guid').val().substring(0, 7) + '@ninkip2p.com'); - setTimeout(updateUI(), 200); + $('#createaccount').bind("touchstart", function () { + Engine.Device.deleteStorageItem("dataCache"); + //Engine.Device.deleteStorageItem("balance"); - window.updateUIInterval = setInterval(function () { + if (window.cordova) { + cordova.plugins.Keyboard.disableScroll(true); + } - updateUI(); + isCreate = true; + $("#pairDevice").hide(); - }, 10000); + }); - } else { - //if the app has not been initialised then we need to download the wallet data - $("#pairspinner").show(); - var target = document.getElementById('pairspinner'); - var spinner = new Spinner(spinneropts).spin(target); - $("#pinspinner").hide(); - $('.numdone').attr("style", "background-color:white"); - $("#loginpin").hide(); - $("#loginpinno").val(''); - pinlock = false; - $("#paddel").hide(); - $("#pinloginmessage").text("Enter your PIN number"); + $('#createaccount').bind("touchend", function () { + setTimeout(function () { - //get the encrypted user's password from local storage - Engine.Device.getStorageItem("ninki_p", function (result) { + $("#createWalletStart").show(); - //decrypt the password using the encryption key sent from the server - //and set the password - var enc = JSON.parse(result); - result = ''; - Engine.setStretchPass(Engine.decryptNp(enc.ct, ekeyv.DeviceKey, enc.iv)); + }, 100); - //get the encrypted 2fa override token from local storage - Engine.Device.getStorageItem("ninki_rem", function (res) { + }); - if (res.length > 0) { + $('#closetos').bind("touchstart", function () { + $("#tos").removeClass("slideUp"); + $("#tos").addClass("invis"); + $("#tos").hide(); - //decrypt the 2fa overide token - var enc = JSON.parse(res); - var fatoken = Engine.decryptNp(enc.ct, ekeyv.DeviceKey, enc.iv); + }); - - //use the token to open the wallet - Engine.openWallet(guid, fatoken, function (err, result) { - if (!err) { + $('#termslink').bind("click", function () { + $("#tos").removeClass("invis"); + $("#tos").addClass("slideUp"); + $('#tos').show(); + }); - //if this is true it means the 2fa token has expired - if (result.TwoFactorOnLogin) { - $("#pairspinner").hide(); - $("#loginpinno").val(''); - pinlock = false; - //$("#enterpinalert").show(); - //$("#enterpinalertmessage").text('Token has expired'); + var options = {}; + options.ui = { + container: "#pwd-container", + showVerdictsInsideProgressBar: true, + showPopover: false, + showErrors: false, + viewports: { + progress: ".pwstrength_viewport_progress" + } + }; + options.common = { + debug: true, + onLoad: function () { + $('#messages').text('Start typing password'); + }, + onKeyUp: function () { + $("#createwalletalert").fadeOut(100); + } + }; - bootbox.alert("Your token has expired. Please repair your device", function () { + $('#createWalletStart #cpassword').pwstrength(options); - Engine.Device.deleteStorageItem("ninki_reg"); - Engine.Device.deleteStorageItem("ninki_p"); - Engine.Device.deleteStorageItem("ninki_rem"); - Engine.Device.deleteStorageItem("guid"); + $("#cpassword").blur(function () { + $(".popover.fade.bottom.in").hide(); + $("#pwdmeter").fadeOut(500); + }); - location.reload(); + $("#cpassword").focus(function (e) { - }); + $(".popover.fade.bottom.in").show(); + $("#pwdmeter").fadeIn(500); - } else { + }); + $("#password1").blur(function () { - //setup local settings - Engine.Device.getStorageItem("currency", function (res) { + }); - if (res) { + $("#password1").focus(function (e) { - Engine.m_settings.LocalCurrency = res; + }); - } else { - Engine.Device.setStorageItem("currency", Engine.m_settings.LocalCurrency); - } - //console.log(Engine.m_settings.LocalCurrency); - //console.log(Engine.m_settings.CoinUnit); - var t = Engine.m_settings.LocalCurrency; + //wallet security wizard - $('.sccy').filter(function () { - return $(this).text().trim() == t; - }).find("label").html(''); + var step = 0; + $(".next").bind("touchstart", function () { - Engine.Device.getStorageItem("coinunit", function (res) { + if (step == 2) { - if (res) { + $("#btnPairDevice").removeClass("disabled"); - Engine.m_settings.CoinUnit = res; + $('#btnUnpair').hide(); + $('#loginpin').show(); + $("#hotkeystep").hide(); - } else { + setTimeout(function () { + $("#hotkeystep").removeClass("fadeInRightBig"); + $("#hotkeystep").addClass("fadeInLeftBig"); - Engine.Device.setStorageItem("coinunit", Engine.m_settings.CoinUnit); - } + }, 1000); - var tc = Engine.m_settings.CoinUnit; - $('.scoinunit').filter(function () { - return $(this).text().trim() == tc; - }).find("label").html(''); + $(".next").hide(); + $(".previous").show(); + step++; + } - }); + if (step == 1) { + $("#hotkeystep").show(); + $("#coldkeystep").hide(); - }); + setTimeout(function () { + $("#coldkeystep").removeClass("fadeInRightBig"); + $("#coldkeystep").addClass("fadeInLeftBig"); + }, 1000); - //initilaise the UI elements - initialiseDashboard(function () { + $(".previous").show(); + $(".next").hide(); - Engine.m_appInitialised = true; + step++; + } - $("#isactive").val(1); + }); - $("#pairspinner").hide(); + $(".previous").bind("touchstart", function () { - $('#dashboard').show(); - $('#dashheader').show(); + if (step == 2) { - $("#mainWallet").show(); - $("#footermode").val(1); - $(".footer").show(); + $("#coldkeystep").show(); + $("#hotkeystep").hide(); - $("#nonlogin").show(); - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } + $("#hotkeystep").removeClass("fadeInLeftBig"); + $("#hotkeystep").addClass("fadeInRightBig"); - }); + $("#hotcheckicon").removeClass("fa-check-square"); + $("#hotcheckicon").removeClass("text-success"); + $("#hotcheckicon").addClass("fa-square-o"); - } + $(".previous").hide(); + $(".next").show(); + step--; + } - } else { + if (step == 3) { + $("#hotkeystep").show(); + $("#emailstep").hide(); - if (result == "ErrLocked") { + $(".previous").show(); + $(".next").show(); + step--; + } - bootbox.alert("Your account is locked. Please unlock your account using the Chrome App"); + if (step == 4) { - } else { + $("#step3").show(); + $("#step4").hide(); - bootbox.alert(result); + $(".previous").show(); + step--; + } - } + }); - $("#pairspinner").hide(); - $('.numdone').attr("style", "background-color:white"); - $("#loginpin").show(); - $("#loginpinno").val(''); - pinlock = false; - $("#paddel").hide(); - $("#pinloginmessage").text("Enter your PIN number"); - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } + $("#coldcheck").bind("touchstart", function () { - } + $("#coldcheckicon").removeClass("fa-square-o"); + $("#coldcheckicon").addClass("fa-check-square"); + $("#coldcheckicon").addClass("text-success"); - }); + $(".next").show(); - } + }); - }); - }); + $("#hotcheck").bind("touchstart", function () { - } + $("#hotcheckicon").removeClass("fa-square-o"); + $("#hotcheckicon").addClass("fa-check-square"); + $("#hotcheckicon").addClass("text-success"); - } else { + $(".next").show(); - $("#pinspinner").hide(); + }); - if (ekeyv == "ErrDeviceDestroyed") { + $("#coldconf").change(function () { + if (this.checked) { + $(".next").show(); + } else { + $(".next").hide(); + } + }); - Engine.Device.deleteStorageItem("ninki_reg"); - Engine.Device.deleteStorageItem("ninki_p"); - Engine.Device.deleteStorageItem("ninki_rem"); - Engine.Device.deleteStorageItem("guid"); + $("#hotconf").change(function () { + if (this.checked) { + $(".next").show(); + } else { + $(".next").hide(); + } + }); - bootbox.alert("Too many failed attempts. The device has been unpaired.", function () { - $("#loginpin").hide(); - $("#mainWallet").hide(); - $("#pairDevice").show(); + $("#chkhotmig").change(function () { + if (this.checked) { + $("#hotmigcont").show(); + } else { + $("#hotmigcont").hide(); + } + }); - location.reload(); - }); + //on blur email + //on blur username - } else { - $("#loginpinno").val(''); - pinlock = false; - $('.numdone').attr("style", "background-color:white"); - $("#paddel").hide(); + var isCreateEmailValid = false + $("#emailaddress").blur(function () { - if (ekeyv.substring(0, 6) == "ErrPIN") { + var emailaddr = $("#emailaddress").val(); + //check email address valid - var attempts = ekeyv.substring(7, 8); + if (emailaddr.length > 2) { - $("#pinloginmessage").text("Incorrect PIN " + attempts + "/3 attempts"); + if ($("#emailaddress").parsley().isValid()) { - $("#pincounter").effect("shake"); + Engine.doesEmailExist(emailaddr, function (err, res) { - } else { + if (res) { - bootbox.alert(ekeyv); - } + var specificField = $('#emailaddress').parsley(); + window.ParsleyUI.addError(specificField, "emailaddressError", "This email address is already taken"); - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } - } + $("#btnCreate").prop('disabled', true); + $("#btnCreate").addClass('disabled'); + $("#emailaddress").css("border-color", "#ffaaaa"); + isCreateEmailValid = false; - } + } else { - }); + $("#emailaddress").css("border-color", "#ccc"); + isCreateEmailValid = true; - }); + } - } else { + validateCreateForm(); - $("#pinspinner").hide(); + }); + } else { - } + $("#emailaddress").parsley().validate(); - } + } + } else { + $("#emailaddress").parsley('reset'); + isCreateNicknameValid = false; + validateCreateForm(); + } - //device paring - var deviceName = ''; - var regToken = ''; - var secret = ''; - var enck = ''; - var iv = ''; + }); - //the user scans a QR code containing data encrypted with the server generated encryption key + var isCreateNicknameValid = false - function pairDevice() { + $("#nickname").focus(function () { + var specificField = $('#nickname').parsley(); + window.ParsleyUI.removeError(specificField, "nicknameError"); - $("#btnPairDevice").addClass("disabled"); + }); - var blob = $('#pairdeviceblob').val(); - var pwd = $('#pairpwd').val(); + $("#emailaddress").focus(function () { - var splitBlob = blob.split('|'); + var specificField = $('#emailaddress').parsley(); + window.ParsleyUI.removeError(specificField, "emailaddressError"); - //console.log(splitBlob.length); + }); - if (splitBlob.length == 5) { + $("#nickname").blur(function () { + var nicknme = $("#nickname").val(); - if (!(typeof window.app === 'undefined')) { - app.isScanning = true; - } + if (nicknme.length > 2) { - var guid = splitBlob[2]; + if ($("#nickname").parsley().isValid()) { - //encrypted hot key and 2fa override token - enck = splitBlob[0]; - iv = splitBlob[1]; - //device name eg. My iPhone - deviceName = splitBlob[3]; + //check email address valid + Engine.doesUsernameExist(nicknme, function (err, res) { - //registration token for this pairing attempt - regToken = splitBlob[4]; + if (res) { - //password enetered by the user - Engine.setPass(pwd, guid); + $("#btnCreate").prop('disabled', true); + $("#btnCreate").addClass('disabled'); + $("#nickname").css("border-color", "#ffaaaa"); - var bytes = []; - for (var i = 0; i < guid.length; ++i) { - bytes.push(guid.charCodeAt(i)); - } + var specificField = $('#nickname').parsley(); + window.ParsleyUI.addError(specificField, "nicknameError", "This username is already taken"); - var hashguid = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(bytes)).toString(); + isCreateNicknameValid = false; + } else { - Engine.m_guid = hashguid; - Engine.m_oguid = guid; + $("#nickname").css("border-color", "#ccc"); + isCreateNicknameValid = true; + } - //first validate the password with the secret + validateCreateForm(); - Engine.getRecoveryPacket(function (err, response) { + }); - if (err) { - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } + } else { - bootbox.alert("There was an error, please try again."); - $("#btnPairDevice").removeClass("disabled"); + $("#nickname").parsley().validate(); + } - } else { + } else { - //decrypt packet and set the secret - //the user will be asked next to choose a PIN - var jpacket = JSON.parse(response); - secret = Engine.decryptNp(jpacket.packet, Engine.m_password, jpacket.IV); + $("#nickname").parsley('reset'); + isCreateNicknameValid = false; + validateCreateForm(); + $("#nickname").css("border-color", "#ffaaaa"); + } - Engine.validateSecret(secret, function (err, secvalid) { + }); - if (!err) { - if (secvalid) { + $("#password1, #cpassword, #emailaddress").change(function () { - //show pin screen + validateCreateForm(); - $('#pairDevice').hide(); - $("#btnPairDevice").removeClass("disabled"); - $('#loginpin').show(); + }); - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } - } - } else { + var showlogo = true; + $("#password1, #cpassword, #nickname, #emailaddress").focus(function () { + showlogo = false; + $("#createheader").slideUp(); + //$("#createheadermini").slideDown(); + termslink + $("#termslink").fadeOut(); + $("#createback").fadeOut(); + }); - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } + $("#password1, #cpassword, #nickname, #emailaddress").blur(function () { + showlogo = true; + setTimeout(function () { + if (showlogo) { - $("#btnPairDevice").removeClass("disabled"); + $("#termslink").fadeIn(); + $("#createback").fadeIn(); - if (secvalid == "ErrAccount") { - bootbox.alert("Password not correct"); - } else if (secvalid == "ErrLocked") { - bootbox.alert("The account is locked"); - } else { - bootbox.alert("There was an error, please try again"); - } + } + }, 50); + }); - } + $("#createback").bind("touchstart", function () { - }); + isCreate = false; + $("#pairDevice").show(); + $("#createWalletStart").hide(); - } + }); - }); - } else { + function validateCreateForm() { - $("#btnPairDevice").removeClass("disabled"); - bootbox.alert("There was a pairing error, please try again."); + if (($(".password-verdict").html() == 'Strong' || $(".password-verdict").html() == 'Very Strong')) { - // $('#pairdevicealertmessage').text("There was a pairing error"); - //$('#pairdevicealert').show(); - } + if (isCreateNicknameValid && isCreateEmailValid) { - } + $("#btnCreate").prop('disabled', false); + $("#btnCreate").removeClass('disabled'); + } else { - function regPIN() { + $("#btnCreate").prop('disabled', true); + $("#btnCreate").addClass('disabled'); - //the user has chosen a PIN and can now register the deive with the server + } - $("#pairspinner").show(); - var target = document.getElementById('pairspinner'); - var spinner = new Spinner(spinneropts).spin(target); + } else { - $('#loginpin').hide(); + $("#btnCreate").prop('disabled', true); + $("#btnCreate").addClass('disabled'); + } - if (!(typeof window.app === 'undefined')) { - app.isScanning = true; } + $("#btnCreate").bind("touchstart", function () { - //hash the pin and device id - var deviceid = "DEVICE123456789"; - if (window.cordova) { - deviceid = window.device.uuid; - } + showlogo = false; + if (isCreateNicknameValid && isCreateEmailValid) { - //hash the PIN with the device id - //this is used to validate the PIN and lookup the encryption key on our server + if ($("#frmcreate").parsley().isValid()) { - var pin = $("#loginpinno").val(); + //check password strength + if (($(".password-verdict").html() == 'Strong' || $(".password-verdict").html() == 'Very Strong')) { - var pinhash = deviceid + pin; - bytes = []; - for (var i = 0; i < pinhash.length; ++i) { - bytes.push(pinhash.charCodeAt(i)); - } + var nicknme = $("#nickname").val(); + //check email address valid + Engine.doesUsernameExist(nicknme, function (err, res) { - pinhash = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(bytes)).toString(); + if (!res) { + var emailaddr = $("#emailaddress").val(); + //check email address valid + Engine.doesEmailExist(emailaddr, function (err, res) { - //new register device + if (!res) { - //enter password - //stretch - //get validate - //if valid - //choose a PIN - //register + $("#imgcreatewaiting").show(); + $("#btnCreate").prop('disabled', true); + $("#btnCreate").addClass('disabled'); + $("#lnkOpenWallet").hide(); + //error handling here? - var devplatform = "platform"; - var devmodel = "model"; + var guid = $('#createWalletStart input#guid').val(); + var username = $("#createWalletStart input#nickname").val(); + var password = $('#createWalletStart input#cpassword').val(); + var emailAddress = $('#createWalletStart input#emailaddress').val(); - if (window.cordova) { - devplatform = window.device.platform; - devmodel = window.device.model; - } - //the device is registered with the server - //authentication via: - //generation of the pairing data required 2 factor authenticaton - // guid as an identifier - // registration token for this pairing session - //secret, which proves the user knows their password - //their chosen PIN number is registered with the server vi a hash of the PIN + Device uuid - //a 256 bit encryption key is generated on the server using a CSPRNG, this is used to encrypt data stored on the device + Engine.m_nickname = username; - Engine.registerDevice(Engine.m_guid, deviceName, devplatform, devmodel, pinhash, regToken, secret, function (err, result) { - if (!err) { + $("#createWalletStart").hide(); + $("#createWalletProgress").show(); - var dk = JSON.parse(result); - if (dk.DeviceKey.length > 0) { + setTimeout(function () { - //the server returns the encryption key - //whcih is used to decrypt the hotkey and 2fa override token + Engine.createWallet(guid, password, username, emailAddress, function (err, result) { - var decblob = Engine.decryptNp(enck, dk.DeviceKey, iv); + //move error handling and ui elements to here + $("#createWalletStart input#nickname").css("border-color", "#ccc"); + if (err) { - //slice it up - //64 64 - var hk = decblob.substring(0, 64); - var fatoken = decblob.substring(64, 128); + if (result == "ErrUserExists") { - //encrypt the user's password with the encryption key - var encp = Engine.encryptNp(Engine.m_password, dk.DeviceKey); - result = ''; + $("#createWalletStart input#nickname").css("border-color", "#ffaaaa"); + $("#imgcreatewaiting").hide(); - var ptok = {}; - ptok.ct = encp.toString(); - ptok.iv = encp.iv.toString(); - var ptoken = JSON.stringify(ptok); + $("#createwalletalert").show(); + $("#createwalletalertmessage").text("The username already exists"); - //encrypt the 2fa override token with the device key - var enc = Engine.encryptNp(fatoken, dk.DeviceKey); - var ctok = {}; - ctok.ct = enc.toString(); - ctok.iv = enc.iv.toString(); + $("#btnCreate").prop('disabled', false); + $("#btnCreate").removeClass('disabled'); + $("#lnkOpenWallet").show(); + } + if (result == "ErrEmailExists") { - var ctoken = JSON.stringify(ctok); + $("#createWalletStart input#emailaddress").css("border-color", "#ffaaaa"); + $("#imgcreatewaiting").hide(); - //encrypt the hotkey with the device key - var ench = Engine.encryptNp(hk, dk.DeviceKey); - var htok = {}; - htok.ct = ench.toString(); - htok.iv = ench.iv.toString(); + $("#createwalletalert").show(); + $("#createwalletalertmessage").text("The email address is already in use"); - var hkey = JSON.stringify(htok); + $("#btnCreate").prop('disabled', false); + $("#btnCreate").removeClass('disabled'); + $("#lnkOpenWallet").show(); + } - dk.DeviceKey = ''; + if (result == "ErrCreateAccount") { - Engine.Device.setStorageItem("guid", Engine.m_oguid); + $("#imgcreatewaiting").hide(); + $("#btnCreate").prop('disabled', false); + $("#btnCreate").removeClass('disabled'); + $("#lnkOpenWallet").show(); - //test opening the wallet + $("#createwalletalert").show(); + $("#createwalletalertmessage").text("Error"); - Engine.openWallet(Engine.m_oguid, fatoken, function (err, result) { + } - if (!err) { + if (result == "ErrSavePacket") { - if (!result.TwoFactorOnLogin) { + $("#imgcreatewaiting").hide(); + $("#btnCreate").prop('disabled', false); + $("#btnCreate").removeClass('disabled'); + $("#lnkOpenWallet").show(); - //if succesfull store the encrypted data in local storage + $("#createwalletalert").show(); + $("#createwalletalertmessage").text("Error"); - Engine.Device.setStorageItem("ninki_rem", ctoken); - Engine.Device.setStorageItem("ninki_p", ptoken); - Engine.Device.setStorageItem("ninki_reg", regToken); - Engine.Device.setStorageItem("ninki_h", hkey); + } - $("#loginpinno").val(''); - pinlock = false; - $("#paddel").hide(); - $('.numdone').attr("style", "background-color:white"); - var t = Engine.m_settings.LocalCurrency; - $('.sccy').filter(function () { - return $(this).text().trim() == t; - }).find("label").html(''); + } else { - var tc = Engine.m_settings.CoinUnit; - $('.scoinunit').filter(function () { - return $(this).text().trim() == tc; - }).find("label").html(''); + $("#hotWalletPhrase").text(result.hotWalletPhrase); + $("#coldWalletPhrase").text(result.coldWalletPhrase); + $("#coldWalletPhrasePrintText").text(result.coldWalletPhrase); + if (Engine.Device.isiOS()) { + deviceName = "My iPhone"; + } else { + deviceName = "My Android"; + } - isPairing = false; + //now we perform a pairing of the device with the account + Engine.getDeviceTokenForApp(deviceName, function (err, response) { - //callback here before displaying + if (!err) { + response = JSON.parse(response); + //registration token for this pairing attempt + regToken = response.RegToken; + fatoken = response.DeviceToken; - initialiseDashboard(function () { + Engine.getHotHash(Engine.m_password, function (err, hothash) { - Engine.m_appInitialised = true; + if (!err) { - $("#pairspinner").hide(); - $('#dashboard').show(); - $('#dashheader').show(); + //encrypt the user's password with the encryption key - $("#footermode").val(1); - $("#mainWallet").show(); - $(".footer").show(); + Engine.Device.setStorageItem("ninki_reg", response.RegToken); - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } + Engine.Device.setSecureStorageObject("ninki_rem", response.DeviceToken, response.DeviceKey, Engine.encryptNp); + Engine.Device.setSecureStorageObject("ninki_p", Engine.m_password, response.DeviceKey, Engine.encryptNp); + Engine.Device.setSecureStorageObject("ninki_h", hothash, response.DeviceKey, Engine.encryptNp); - }); + result = ''; - } else { + //save all the tokens + //we should now be in the same state as if we have just + //scanned a qr code to pair the phone + //and entered a password - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } + //initialiseUI(); + //Engine.m_validate = false; - $("#pairspinner").hide(); - bootbox.alert("Could not pair", function () { + //set variables for the session + $("#createWalletStart").hide(); + $("#createWalletProgress").hide(); - location.reload(); + $('#createWalletStart input#cpassword').val(''); + $('#createWalletStart input#password1').val(''); - }); + //save the encrypted hot key in local storage - } + $("#walletGuid").text($('input#guid').val()); + $("#showPhrases").show(); + $("#securitywizard").show(); - } else { + $(".next").hide(); - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } + $("#no2famessage").hide(); - $("#pairspinner").hide(); + step = 1; + $("#coldkeystep").show(); + $(".previous").hide(); + } - bootbox.alert(result, function () { + }); - location.reload(); + } - }); + }); - } - }); - } else { + //showTwoFactorQr(); - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; - } + } + }, function (txtprogress) { + $("#progresstext").text(txtprogress); - $("#pairspinner").hide(); - bootbox.alert("The pairing token has expired", function () { + }); - location.reload(); + }, 100); + } else { - }); + isCreateEmailValid = false; + validateCreateForm(); + } + }); - } + } else { + isCreateNicknameValid = false; + validateCreateForm(); + } + }); - } else { + } else { + //password not strong + $("#createwalletalert").show(); + $("#createwalletalertmessage").text("Password must be Strong- ideally Very Strong"); + } - if (!(typeof window.app === 'undefined')) { - app.isScanning = false; + } else { + + $("#frmcreate").parsley().validate(); } + } - $("#pairspinner").hide(); - bootbox.alert(result, function () { + }); - location.reload(); - }); + $("#tfacopy").bind("touchstart", function () { - } - }); + if (window.cordova) { + cordova.plugins.clipboard.copy($("#tfarawcode").text(), function () { - secret = ''; + $('#tfarawcode').addClass("backgroundAnimated"); + setTimeout(function () { + $('#tfarawcode').removeClass("backgroundAnimated"); + }, 1000); - } + }, function () { + console.log("copy error"); + }); + } else { - function closeSendNet() { + $('#tfarawcode').addClass("backgroundAnimated"); + setTimeout(function () { + $('#tfarawcode').removeClass("backgroundAnimated"); + }, 1000); + } + }); - $("#dashsend").addClass("invis"); - $("#dashsend").removeClass("slideUp"); - $("#dashsend").hide(); + $("#tfaoptsetup").bind("touchstart", function () { - $("#dashsendamt").addClass("invis"); - $("#dashsendamt").removeClass("slideUp"); - $("#dashsendamt").hide(); - $("#mainWallet").show(); + showTwoFactorQr(); - if (sendmode == "net" || sendmode == "inv") { - $("#friendheader").show(); - } else { - $('#dashboard').show(); - $('#dashheader').show(); + $("#tfaoption").hide(); + $("#tfaoptionsetuppnl").show(); - } - $(".footer").show(); + }); - $("#dashreceive").addClass("invis"); - $("#dashreceive").removeClass("slideUp"); - $("#dashreceive").hide(); + $("#tfaoptsetuplater, #tfaoptclose").bind("touchstart", function () { - $("#dashcontact").addClass("invis"); - $("#dashcontact").removeClass("slideUp"); - $("#dashcontact").hide(); - //$("#dashreceive").hide(); - //$("#dashcontact").hide(); + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } - $("#pinconfirm").hide(); + $("#tfastep").hide(); - $("#btnStdSndDone").hide(); + $("#imgphrasewaiting").hide(); - $('#toAddress').val(''); + $("#welcome").removeClass("invis"); + $("#welcome").addClass("slideUp"); + $("#welcome").show(); - sendAmount = ''; - updateStdAmount(); + }); - } + $("#btnletsrock").bind("touchstart", function () { - function closeSendStd() { + $("#welcome").addClass("invis"); + $("#welcome").removeClass("slideUp"); + $("#welcome").hide(); + $('#welcome').hide(); + $('#dashboard').show(); + $('#dashheader').show(); - $("#dashsend").removeClass("slideUp"); - $("#dashsend").addClass("invis"); - $("#dashsend").hide(); + $("#footermode").val(1); + $("#mainWallet").show(); + $(".footer").show(); - $("#dashsendamt").removeClass("slideUp"); - $("#dashsendamt").addClass("invis"); - $("#dashsendamt").hide(); + }); - $('#dashboard').show(); - $('#dashheader').show(); - $("#mainWallet").show(); - $(".footer").show(); + $("#qrtab").bind('touchstart', function (e) { + $("#tabqr").show(); + $("#tabman").hide(); + $("#liman").removeClass('active'); + $("#liqr").addClass('active'); + $("#btnPassphraseLogin").text("Setup Authenticator"); + }); + $("#mantab").bind('touchstart', function (e) { + $("#tabman").show(); + $("#tabqr").hide(); + $("#liqr").removeClass('active'); + $("#liman").addClass('active'); + $("#btnPassphraseLogin").text("Paste from Clipboard"); - $("#dashreceive").removeClass("slideUp"); - $("#dashreceive").addClass("invis"); - $("#dashreceive").hide(); + }); - $("#dashcontact").removeClass("slideUp"); - $("#dashcontact").addClass("invis"); - $("#dashcontact").hide(); - $("#pinconfirm").hide(); - $("#btnStdSndDone").hide(); + var useClipboardTFA = true; + $("#twoFactorCodeCheck").focus(function () { - //profilepagestate = "send"; - //menustate = "profile" + useClipboardTFA = false; + $("#btnPassphraseLogin").text("Setup Authenticator"); - $('#toAddress').val(''); + if ($("#liman").hasClass("active")) { + $("#tabman").slideUp(); + } - sendAmount = ''; + if ($("#liqr").hasClass("active")) { + $("#tabqr").slideUp(); + } + }); - updateStdAmount(); + $("#twoFactorCodeCheck").blur(function () { - } - var stdAmountConvCoin = true; - var netAmountConvCoin = true; + if ($("#liman").hasClass("active")) { + useClipboardTFA = true; + $("#btnPassphraseLogin").text("Paste from Clipboard"); + } - function convertToLocalCurrency(amount) { + if ($("#liman").hasClass("active")) { + $("#tabman").slideDown(); + } - var conv = amount; - conv = conv * 1.0; + if ($("#liqr").hasClass("active")) { + $("#tabqr").slideDown(); + } + }); - var sats = convertToSatoshis(conv, COINUNIT); - var btc = convertFromSatoshis(sats, "BTC"); + $("#btnPassphraseLogin").bind("touchstart", function () { - var cbtc = btc * price; + var twoFactorCodeChk = $('#twoFactorCodeCheck').val(); + if (useClipboardTFA) { - var loc = "en-US"; - var ires = cbtc; + if (window.cordova) { - if (Engine.m_settings.LocalCurrency == "JPY") { - ires = (cbtc * 1.0).toFixed(0) * 1.0; - } else { - ires = (cbtc * 1.0).toFixed(2) * 1.0; - } + cordova.plugins.clipboard.paste(function (text) { - var loc = "en-US"; - var cprc = ""; - if (Engine.m_settings.LocalCurrency == "JPY" || Engine.m_settings.LocalCurrency == "CNY") { - cprc = accounting.formatMoney(ires, "¥", 0); - } else if (Engine.m_settings.LocalCurrency == "GBP") { - cprc = accounting.formatMoney(ires, "£", 2); - } else if (Engine.m_settings.LocalCurrency == "EUR") { - cprc = accounting.formatMoney(ires, "€", 2); - } else if (Engine.m_settings.LocalCurrency == "USD") { - cprc = accounting.formatMoney(ires, "$", 2); - } else if (Engine.m_settings.LocalCurrency == "CNY") { - cprc = accounting.formatMoney(ires, "¥", 2); - } + $("#twoFactorCodeCheck").val(text); + setup2fa(); - return cprc; - } + }, function () { + //console.log("paste error"); - function convertFromLocalCurrency(amount, format) { + }); + } - var conv = amount; - conv = conv * 1.0; + } else { + setup2fa(); + } - //convert to bitcoin - if (price > 0) { - var cbtc = conv / price; - var sats = convertToSatoshis(cbtc, "BTC"); + }); - var dp = 4; - if (sats > 0 && sats < 10000) { - dp = 8; - } + function setup2fa() { - var btc = convertFromSatoshis(sats, COINUNIT); + var twoFactorCodeChk = $('#twoFactorCodeCheck').val(); + //add basic validation - if (format) { - if (COINUNIT == "BTC") { + if (twoFactorCodeChk.length < 6) { - btc = accounting.formatMoney(btc, "", dp); + //add red border + $('#twoFactorCodeCheck').css("border-color", "#ffaaaa"); + return; - } + } - if (COINUNIT == "Bits") { + $("#btnPassphraseLogin").prop('disabled', true); - btc = accounting.formatMoney(btc, "", 0); + Engine.SetupTwoFactor(twoFactorCodeChk, function (err, result) { - } - } else { + if (err) { - if (COINUNIT == "BTC") { - var dpr = 4; - if (sats > 0 && sats < 10000) { - dpr = 8; - } + $("#tfaerror").text("Invalid code"); - btc = accounting.toFixed(btc, dpr); - } + $("#btnPassphraseLogin").prop('disabled', false); - if (COINUNIT == "Bits") { - var dpr = 0; - if (sats > 0 && sats < 10000) { - dpr = 2; + } else { + + $("#twoFactorCodeCheck").blur(); + $("#tfaerror").text(''); + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; } - btc = accounting.toFixed(btc, dpr); - } - } + $("#tfastep").hide(); - return btc; + $("#welcome").removeClass("invis"); + $("#welcome").addClass("slideUp"); + $("#welcome").show(); - } else { + } - return 0; - } + }); + } - } - var sendAmount = ''; + $("#btnEmailValidate").bind("touchstart", function () { - function updateStdAmount() { + //app.isScanning = false; - //vamout will track the value - //hdamount.val is the value actually used as an - // input to the transaction + if (window.cordova) { + cordova.plugins.clipboard.paste(function (text) { - //if the input value is decimal . or empty - //set to 0 - var vAmount = 0; - if (sendAmount == '' || sendAmount == '.') { - vAmount = 0; - } else { - vAmount = sendAmount; - } + var ttext = text.trim().replace(" ", ""); + //$('#txtEmailToken').val(''); + $('#txtEmailToken').val(ttext); + $("#txtEmailToken").trigger('change'); - vAmount = vAmount * 1; + }, function () { - if (sendAmount == '') { + //console.log("paste error"); - //default entry box and actual value in the case of no input - $('#amount').text('amount'); - if (stdAmountConvCoin) { - $('#ccystdamt').html(convertToLocalCurrency(0)); - } else { - $('#ccystdamt').html(convertFromLocalCurrency(0) + ' ' + COINUNIT); + }); } - $('#hdamount').val('0'); - - } else { - if (stdAmountConvCoin) { + }); - //amounts are being input in a Bitcoin denomination - //so we convert to local currenct + $("#txtEmailToken").change(function () { - $('#ccystdamt').html(convertToLocalCurrency(vAmount)); - //convert bitcoin amount to number - $('#hdamount').val(vAmount * 1.0); + var token = $("#txtEmailToken").val(); - var cprc = 0; - if (COINUNIT == "Bits") { + $("#btnEmailValidate").prop('disabled', true); - //default bits to 0 decimal places - cprc = accounting.formatMoney(sendAmount, "", 0); + Engine.getEmailValidation(token, function (err, response) { + if (err) { + $("#btnEmailValidate").prop('disabled', false); } else { + if (response != "Valid") { - var indot = sendAmount.indexOf('.'); + if (response == "Expired") { + $("#valemailerror").text('Your token has expired'); + } + if (response == "Invalid") { + $("#valemailerror").text('Your token is not valid'); + } - //if the input is the beginning of input entry - //apply no formatting - if (sendAmount == '.' || sendAmount == '0.' || sendAmount == '0') { + $("#btnEmailValidate").prop('disabled', false); - cprc = sendAmount; - } - else if (indot == sendAmount.length - 1) { - //if the user has just enetered a decimal point - //format the number and add on the decimal for display - cprc = accounting.formatMoney(sendAmount, "", 0) + '.'; - } - else { - //if there is no decimal point apply formatting - //with 0 dp - if (indot == -1) { + $("#valemailerror").show(); + $("#valemailerror").fadeOut(2000); - cprc = accounting.formatMoney(sendAmount, "", 0); + } else { - } else { - //allow bitcoin entry up to 8 decimal places - var ramt = Math.min(sendAmount.length - indot, 9); - ramt = ramt - 1; - cprc = accounting.formatMoney(sendAmount, "", ramt); - } - } + Engine.m_validate = false; - } + $('#createWalletStart').hide(); + $('#emailstep').hide(); - var fee = convertFromSatoshis(Engine.m_settings.MinersFee, COINUNIT); - if ((currentBalance >= (vAmount + fee) && vAmount > 0) && convertToSatoshis(vAmount, COINUNIT) >= 10000) { + // $("#btnPairDevice").removeClass("disabled"); - $('#btnsendmoneystd').removeClass("disabled"); - } else { + $("#tfastep").show(); - $('#btnsendmoneystd').removeClass("disabled"); - $('#btnsendmoneystd').addClass("disabled"); - } + $("#pairspinner").hide(); - $('#amount').text(cprc); - } - else { + //$('#btnUnpair').hide(); + //$('#loginpin').show(); - //entry is in local currency - //so we need to convert to coin units and also format - //the currency input - var amt = convertFromLocalCurrency(vAmount); - var amtfmt = convertFromLocalCurrency(vAmount, true); - amt = amt * 1.0; + $("#validateemail").hide(); + $("#valemailerror").hide(); + $("#btnEmailValidate").prop('disabled', false); - $('#hdamount').val(amt); - $('#ccystdamt').text(amtfmt + ' ' + COINUNIT); - - var symb = ''; - if (Engine.m_settings.LocalCurrency == "JPY" || Engine.m_settings.LocalCurrency == "CNY") { - symb = "¥"; - } else if (Engine.m_settings.LocalCurrency == "GBP") { - symb = "£"; - } else if (Engine.m_settings.LocalCurrency == "EUR") { - symb = "€"; - } else if (Engine.m_settings.LocalCurrency == "USD") { - symb = "$"; - } else if (Engine.m_settings.LocalCurrency == "CNY") { - symb = "¥"; - } - - - var cprc = ''; - - var indot = sendAmount.indexOf('.'); - - if (sendAmount == '.' || sendAmount == '0.' || sendAmount == '0') { - - cprc = symb + sendAmount; - - } - else if (indot == sendAmount.length - 1) { - - cprc = accounting.formatMoney(sendAmount, symb, 0) + '.'; - } - else { - - if (indot == -1) { - - cprc = accounting.formatMoney(sendAmount, symb, 0); - - } else { - - var ramt = Math.min(sendAmount.length - indot, 2); - - cprc = symb + sendAmount } - - } - - - var fee = convertFromSatoshis(Engine.m_settings.MinersFee, COINUNIT); - if (currentBalance >= (amt + fee) && amt > 0 && convertToSatoshis(amt, COINUNIT) >= 10000) { - - $('#btnsendmoneystd').removeClass("disabled"); - - } else { - - $('#btnsendmoneystd').removeClass("disabled"); - $('#btnsendmoneystd').addClass("disabled"); } + }); - $('#amount').html(cprc); - } - } - - } - - - var profilepagestate = ''; - var networkpagestate = ''; - var friendpagestate = ''; - var menustate = ''; - - var cl = ''; - - var scrolling = false; - var scrollingnettran = false; - var scrollingnetlist = false; - - jQuery(document).ready(function () { - - var $body = jQuery('body'); + //call to verify token - $("#dashboard").on("scroll", function () { - scrolling = true; }); - $("#dashboard").on("touchstart", function () { - scrolling = false; + //after the user has chosen their PIN + //register the pin with the server - }); - $("#pnlfriend").on("scroll", function () { - scrollingnettran = true; - }); + $("#emailresend").click(function () { - $("#pnlfriend").on("touchstart", function () { + Engine.sendWelcomeDetails(function (err, result) { - scrollingnettran = false; + if (!err) { - }); + $("#emailresendmessage").show(); + $("#emailresend").hide(); + //email has been resent, please check your email + } - $("#networklist").on("scroll", function () { - scrollingnetlist = true; - }); + }); - $("#networklist").on("touchstart", function () { + }); - scrollingnetlist = false; + function showTwoFactorQr() { - }); + $("#twoFactorQr").show(); + $("#2factor1").show(); + Engine.getTwoFactorImg(function (err, twoFASecret) { - bootbox.setDefaults({ 'backdrop': false, 'animate': true }); + var nickname = $("#createWalletStart input#nickname").val(); + var data = "otpauth://totp/Ninki:" + nickname + "?secret=" + twoFASecret + "&issuer=Ninki"; + var options = { text: data, width: 128, height: 128 }; - //guid - //ninki_reg + $('#tfarawcode').text(twoFASecret); - //if device is paired then + $('#twoFactorQrImg').text(''); + $('#twoFactorQrImg').qrcode(options); + }); - Engine.Device.getStorageItem("ninki_reg", function (reg) { + } - if (reg) { - isPairing = false; - $("#loginpin").show(); - $("#pinimage").show(); - } else { - isPairing = true; - $("#pairDevice").show(); - $("#pinpair").show(); - } + //end create wallet area - }); $("#mainWallet").hide(); @@ -1416,14 +1380,140 @@ function UI() { Engine.m_settings.LocalCurrency = sel; - updateUI(); + updatePrice(); }); - //add copy hook for cordova + + $('#tapunlock').bind('touchstart', function () { + + $("#settingsheader").hide(); + $(".footer").hide(); + $("#secwarning").removeClass("invis"); + $("#secwarning").addClass("slideUp"); + $("#secwarning").show(); + $("#secphrasepnl").hide(); + $("#tapsecok").show(); + $("#tapseccancel").text("Cancel"); + $("#mainWallet").hide(); + $("#secwarn").show(); + $("#sechold").hide(); + + }); + + $('#tapseccancel').bind('touchstart', function () { + + + $("#secwarning").addClass("invis"); + $("#secwarning").removeClass("slideUp"); + $("#secwarning").hide(); + $("#mainWallet").show(); + $("#settingsheader").show(); + $(".footer").show(); + + + + $("#secphrasepnl").hide(); + $("#secphrase").text(''); + + }); + + + + + + $('#tapsecok').bind('touchstart', function () { + + + sendmode = "viewkey" + $("#mainWallet").hide(); + $("#secwarning").hide(); + + $("#pinconfdets").hide(); + $("#pinconfirm").show(); + + }); + + $("#secphrasepnl").hammer(null).bind("press", function () { + $("#secphrase").fadeIn(); + setTimeout(function () { + $("#secphrase").fadeOut(2000); + }, 60000); + }); + + + function displayKey() { + + var pin = $('#sendstdpin').val(); + + Engine.getDeviceKey(pin, function (err, ekey) { + + if (!err) { + + Engine.getHotHash(ekey.DeviceKey, function (err, hotHash) { + + if (!err) { + var bip39 = new BIP39(); // 'en' is the default language + var hotmnem = bip39.entropyToMnemonic(hotHash); + $("#secphrase").text(hotmnem); + $("#pinconfirm").hide(); + $("#pinconfdets").show(); + + $("#secwarn").hide(); + $("#sechold").show(); + + + $("#secwarning").removeClass("slideUp"); + $("#secwarning").show(); + $("#secphrasepnl").show(); + $("#secphrase").hide(); + window.resetPin(); + + $("#paddelconf").hide(); + + $('.numdone').attr("style", "background-color:white"); + + $("#sendstdpin").val(''); + + $("#tapsecok").hide(); + $("#tapseccancel").text("Close"); + + } + + }); + + } else { + + + $('.numdone').attr("style", "background-color:white"); + + $("#sendstdpin").val(''); + pintaps = 0; + prevpin = ''; + + + if (ekey.substring(0, 6) == "ErrPIN") { + + var attempts = ekey.substring(7, 8); + + $("#pinconfcount").effect("shake"); + + } else { + + bootbox.alert(ekey); + + } + + + } + + }); + + } + //add copy hook for cordova $('#copyvalphrase').bind('touchstart', function () { if (window.cordova) { @@ -1704,10 +1794,14 @@ function UI() { pintaps = 0; - if (!isPairing) { - loginPIN(); - } else { + + //if create account regPINCreate + if (isCreate) { + regPINCreate(); + } else if (isPairing) { regPIN(); + } else { + loginPIN(); } //only if fail @@ -1822,6 +1916,10 @@ function UI() { payInvoice(selectedInvoiceUserName, selectedInvoiceAmount, selectedInvoiceId); + } else if (sendmode == 'viewkey') { + + displayKey(); + } @@ -1930,7 +2028,7 @@ function UI() { }); - loadInvoices(); + //loadInvoices(); } @@ -2037,6 +2135,7 @@ function UI() { $("#networklistheader").show(); networkpagestate = ""; + SELECTEDFRIEND = ''; } } @@ -2326,11 +2425,30 @@ function UI() { $("#sendstdlabel").text(''); $("#sendstds2add").text(''); $("#sendstdlbli").hide(); + $("#pinconfdets").show(); + + + + window.resetPin(); + + $("#paddelconf").hide(); + + $('.numdone').attr("style", "background-color:white"); + + $("#sendstdpin").val(''); + + if (sendmode == "std") { closeSendStd(); } else if (sendmode == "net") { closeSendNet(); + } else if (sendmode == "viewkey") { + $("#settingsheader").show(); + $(".footer").show(); + $("#pinconfirm").hide(); + $("#mainWallet").show(); + } else { $("#pinconfirm").hide(); $("#invoices").show(); @@ -2447,6 +2565,9 @@ function UI() { sendmode = "net"; + + $("#btnsendmoneystd").addClass("disabled"); + $("#addressinvalid").hide(); $("#sendstdlbli").hide(); @@ -2497,6 +2618,8 @@ function UI() { $("#tapsend").bind('touchstart', function () { + + $("#btnsendmoneystd").addClass("disabled"); $("#addressinvalid").hide(); $("#sendstdlbli").hide(); @@ -2569,6 +2692,11 @@ function UI() { $("#taprequest").bind('touchstart', function () { + + $("#friend").css("border-color", "#ccc"); + $("#addcontactalert").hide(); + $("#addcontactalertmessage").text(""); + $("#networklistheader").hide(); //$("#networklist").hide(); $("#network").hide(); @@ -2583,14 +2711,13 @@ function UI() { }); - }); - - - $(document).ready(function () { $("#pairdeviceblob").change(function () { + Engine.Device.deleteStorageItem("dataCache"); + //Engine.Device.deleteStorageItem("balance"); + if ($("#pairdeviceblob").val().length > 10) { var check = $("#pairdeviceblob").val().split('|'); @@ -2648,6 +2775,8 @@ function UI() { }); //always destroy locally + Engine.Device.deleteStorageItem("dataCache"); + //Engine.Device.deleteStorageItem("balance"); Engine.Device.deleteStorageItem("ninki_rem"); Engine.Device.deleteStorageItem("ninki_p"); Engine.Device.deleteStorageItem("ninki_reg"); @@ -2675,6 +2804,16 @@ function UI() { }); + + + $("#friend").focus(function () { + $("#addcontactqrslide").slideUp(); + }); + + $("#friend").blur(function () { + $("#addcontactqrslide").slideDown(); + }); + $("#btnaddfriend").bind('touchstart', function () { addFriend($('input#friend').val()); @@ -2714,45 +2853,120 @@ function UI() { 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) { + $("#btnVerify").addClass("disabled"); - if (result) { - $("#txtCode").val(''); - selectedFriend.validated = true; - FRIENDSLIST[selectedFriend.userName].validated = true; - updateSelectedFriend(); - $("#networkvalidate").hide(); - $("#friendheader").show(); - $("#mainWallet").show(); - $(".footer").show(); - //update list also + var isAccepted = false; - //find friend in list and update the validated icon - $("#myfriends #seltarget" + selectedFriend.userName).html('
'); + if (FRIENDSLIST[selectedFriend.userName].IsSend) { + isAccepted = true; + } + if (isAccepted) { - } else { - $("#validatefail").show(); - } - }); - }); + Engine.verifyFriendData(SELECTEDFRIEND, code, function (err, result) { + if (result) { - //INVOICE STUFF START------------------------------------------ + $("#txtCode").val(''); + $("#btnVerify").removeClass("disabled"); + selectedFriend.validated = true; + FRIENDSLIST[selectedFriend.userName].validated = true; + updateSelectedFriend(); + $("#networkvalidate").hide(); + $("#friendheader").show(); + $("#mainWallet").show(); + $(".footer").show(); + //update list also - $("#friendselector").hide(); - $("#invoice").hide(); - $("#invoicedisplay").hide(); + //find friend in list and update the validated icon + $("#myfriends #seltarget" + selectedFriend.userName).html('
'); - $("#btnpayinvoice").bind('touchstart', function () { - $("#tapeditamt").hide(); + } else { + $("#btnVerify").removeClass("disabled"); + $("#validatefail").show(); + } + + }, function (message) { + + $("#validateformmess").text(message); + + }); + + } else { + + Engine.acceptFriendRequest(SELECTEDFRIEND, function (err, res) { + + if (!err) { + + Engine.verifyFriendData(SELECTEDFRIEND, code, function (err, result) { + + if (!err) { + + if (result) { + + $("#txtCode").val(''); + $("#btnVerify").removeClass("disabled"); + selectedFriend.validated = true; + FRIENDSLIST[selectedFriend.userName].validated = true; + + updateSelectedFriend(); + updateFriendRequests(); + + $("#validateformmess").text(''); + $("#networkvalidate").hide(); + $("#friendheader").show(); + $("#mainWallet").show(); + $(".footer").show(); + + //update list also + + //find friend in list and update the validated icon + $("#myfriends #seltarget" + selectedFriend.userName).html('
'); + + + } else { + + $("#btnVerify").removeClass("disabled"); + $("#validateformmess").text(''); + $("#validatefail").show(); + } + + } + + }, function (message) { + + $("#validateformmess").text(message); + + }); + + } + + + }, function (message) { + + $("#validateformmess").text(message); + + }); + + } + + + }); + + + //INVOICE STUFF START------------------------------------------ + + $("#friendselector").hide(); + $("#invoice").hide(); + $("#invoicedisplay").hide(); + + $("#btnpayinvoice").bind('touchstart', function () { + + $("#tapeditamt").hide(); $(".footer").hide(); @@ -2786,25 +3000,25 @@ function UI() { Engine.updateInvoice(selectedInvoiceUserName, selectedInvoiceId, '', 2, function (err, result) { - loadInvoices(function (err, res) { + //loadInvoices(function (err, res) { - lastInvoiceToPayCount = 0; + lastInvoiceToPayCount = 0; - showInvoiceListNetwork(); + showInvoiceListNetwork(); - updateSelectedFriend(); + updateSelectedFriend(); - networkpagestate = "friend"; + networkpagestate = "friend"; - $("#invoices").hide(); - $("#mainWallet").show(); - $("#network").show(); - $("#pnlfriend").show(); - $("#friendheader").show(); - $(".footer").show(); + $("#invoices").hide(); + $("#mainWallet").show(); + $("#network").show(); + $("#pnlfriend").show(); + $("#friendheader").show(); + $(".footer").show(); - }); }); + // }); }); @@ -2838,78 +3052,80 @@ function UI() { function showInvoiceListNetwork() { - var invoices = _.filter(cachedInvoices, function (inv) { return inv.InvoiceFrom == SELECTEDFRIEND; }); + //var invoices = _.filter(cachedInvoices, function (inv) { return inv.InvoiceFrom == SELECTEDFRIEND; }); + Engine.getInvoicesToPayNetwork(SELECTEDFRIEND, function (err, invoices) { - if (invoices.length == 0) { - $('#invfornet').empty(); - $('#invfornet').hide(); - } + if (invoices.length == 0) { + $('#invfornet').empty(); + $('#invfornet').hide(); + } - //if (lastInvoiceToPayNetCount < invoices.length) { - lastInvoiceToPayNetCount = invoices.length; + //if (lastInvoiceToPayNetCount < invoices.length) { - var s = ''; - $('#invfornet').empty(); + lastInvoiceToPayNetCount = invoices.length; + + var s = ''; + $('#invfornet').empty(); - for (var i = 0; i < invoices.length; i++) { + for (var i = 0; i < invoices.length; i++) { - var invdate = new Date(invoices[i].InvoiceDate.match(/\d+/)[0] * 1); + var invdate = new Date(invoices[i].InvoiceDate.match(/\d+/)[0] * 1); - var timeLabel = prettydate.format(invdate); + var timeLabel = prettydate.format(invdate); - var statusbox = ''; - if (invoices[i].InvoiceStatus == 0) { - statusbox = ' Pending'; - } - else if (invoices[i].InvoiceStatus == 1) { - statusbox = ' Paid'; - } - else if (invoices[i].InvoiceStatus == 2) { - statusbox = ' Rejected'; - } + var statusbox = ''; + if (invoices[i].InvoiceStatus == 0) { + statusbox = ' Pending'; + } + else if (invoices[i].InvoiceStatus == 1) { + statusbox = ' Paid'; + } + else if (invoices[i].InvoiceStatus == 2) { + statusbox = ' Rejected'; + } - s += "
" + _.escape(timeLabel) + "
" + + s += "
" + _.escape(timeLabel) + "
" + "
" + statusbox + "
"; - } + } + + cachedInvoices = invoices; - $('#invfornet').append(s); + $('#invfornet').append(s); - for (var i = 0; i < invoices.length; i++) { + for (var i = 0; i < invoices.length; i++) { - $("#invfornet #viewinvoicenetfrom" + invoices[i].InvoiceFrom + invoices[i].InvoiceId).hammer(null).bind("tap", { - index: invoices[i].InvoiceId, username: invoices[i].InvoiceFrom - }, function (event) { + $("#invfornet #viewinvoicenetfrom" + invoices[i].InvoiceFrom + invoices[i].InvoiceId).hammer(null).bind("tap", { + index: invoices[i].InvoiceId, username: invoices[i].InvoiceFrom + }, function (event) { - $("#invtapspinner").show(); - var target = document.getElementById('invtapspinner'); - var spinner = new Spinner(spinneropts).spin(target); + $("#invtapspinner").show(); + var target = document.getElementById('invtapspinner'); + var spinner = new Spinner(spinneropts).spin(target); - displayInvoice(event.data.index, event.data.username, 'forme', function (err, res) { - uiInvoiceReturnToNetwork = true; + displayInvoice(event.data.index, event.data.username, 'forme', function (err, res) { + uiInvoiceReturnToNetwork = true; - networkpagestate = "invoice"; - friendpagestate = "invoice"; + networkpagestate = "invoice"; + friendpagestate = "invoice"; - $("#invtapspinner").hide(); - $('#pnlfriend').hide(); - $("#friendheader").hide(); - $(".footer").hide(); - $('#invoices').show(); + $("#invtapspinner").hide(); + $('#pnlfriend').hide(); + $("#friendheader").hide(); + $(".footer").hide(); + $('#invoices').show(); + }); }); - }); - } - - $('#invfornet').show(); + } + $('#invfornet').show(); - //} - // $('#pnlfriendinv').show(); + }); } @@ -2917,75 +3133,81 @@ function UI() { var lastInvoiceByMeNetCount = 0; function showInvoiceByMeListNetwork() { - var invoices = _.filter(cachedInvoicesByUser, function (inv) { return inv.InvoiceFrom == SELECTEDFRIEND; }); + //var invoices = _.filter(cachedInvoicesByUser, function (inv) { return inv.InvoiceFrom == SELECTEDFRIEND; }); - if (invoices.length == 0) { - $('#invbynet').empty(); - $('#invbynet').hide(); - } + Engine.getInvoicesByUserNetwork(SELECTEDFRIEND, function (err, invoices) { + if (invoices.length == 0) { + $('#invbynet').empty(); + $('#invbynet').hide(); + } - if (lastInvoiceByMeNetCount < invoices.length) { - lastInvoiceByMeNetCount = invoices.length; + if (lastInvoiceByMeNetCount < invoices.length) { - var s = ''; - $('#invbynet').empty(); + lastInvoiceByMeNetCount = invoices.length; - for (var i = 0; i < invoices.length; i++) { + var s = ''; + $('#invbynet').empty(); - var invdate = new Date(invoices[i].InvoiceDate.match(/\d+/)[0] * 1); + for (var i = 0; i < invoices.length; i++) { - var timeLabel = prettydate.format(invdate); + var invdate = new Date(invoices[i].InvoiceDate.match(/\d+/)[0] * 1); + var timeLabel = prettydate.format(invdate); - var statusbox = ''; - if (invoices[i].InvoiceStatus == 0) { - statusbox = ' Pending'; - } - else if (invoices[i].InvoiceStatus == 1) { - statusbox = ' Paid'; - } - else if (invoices[i].InvoiceStatus == 2) { - statusbox = ' Rejected'; - } - s += "
" + _.escape(timeLabel) + "
" + + var statusbox = ''; + if (invoices[i].InvoiceStatus == 0) { + statusbox = ' Pending'; + } + else if (invoices[i].InvoiceStatus == 1) { + statusbox = ' Paid'; + } + else if (invoices[i].InvoiceStatus == 2) { + statusbox = ' Rejected'; + } + + s += "
" + _.escape(timeLabel) + "
" + "
" + statusbox + "
"; - } - - $('#invbynet').append(s); + } - for (var i = 0; i < invoices.length; i++) { + cachedInvoicesByUser = invoices; - $("#invbynet #viewinvoicenetby" + invoices[i].InvoiceFrom + invoices[i].InvoiceId).hammer(null).bind("tap", { - index: invoices[i].InvoiceId, username: invoices[i].InvoiceFrom - }, function (event) { + $('#invbynet').append(s); + for (var i = 0; i < invoices.length; i++) { - $("#invtapspinner").show(); - var target = document.getElementById('invtapspinner'); - var spinner = new Spinner(spinneropts).spin(target); + $("#invbynet #viewinvoicenetby" + invoices[i].InvoiceFrom + invoices[i].InvoiceId).hammer(null).bind("tap", { + index: invoices[i].InvoiceId, username: invoices[i].InvoiceFrom + }, function (event) { - displayInvoice(event.data.index, event.data.username, 'byme', function (err, res) { - networkpagestate = "invoice"; - friendpagestate = "invoice"; + $("#invtapspinner").show(); + var target = document.getElementById('invtapspinner'); + var spinner = new Spinner(spinneropts).spin(target); - $("#invtapspinner").hide(); - $('#pnlfriend').hide(); - $("#friendheader").hide(); - $('.footer').hide(); - $('#invoices').show(); + displayInvoice(event.data.index, event.data.username, 'byme', function (err, res) { + + networkpagestate = "invoice"; + friendpagestate = "invoice"; + $("#invtapspinner").hide(); + $('#pnlfriend').hide(); + $("#friendheader").hide(); + $('.footer').hide(); + $('#invoices').show(); + + }); }); - }); - } + } - $('#invbynet').show(); + $('#invbynet').show(); - } + } + + }); // $('#pnlfriendinv').show(); @@ -3057,9 +3279,6 @@ function UI() { $("#tblinvdisplay tfoot th #dtotal").text(accounting.formatNumber(convertFromSatoshis(json.summary.total, COINUNIT), dp, ",", ".")); - - - selectedInvoiceAmount = convertFromSatoshis(json.summary.total); selectedInvoiceId = invoice.InvoiceId; selectedInvoiceUserName = invoice.InvoiceFrom; @@ -3210,9 +3429,8 @@ function UI() { prevNetworkTransCount = -1; prevtransfeed = -1; - showTransactionFeed(function (err, res) { - showTransactionNetwork(); - }); + showTransactionNetwork(); + showTransactionFeed(); updateUI(); @@ -3226,9 +3444,6 @@ function UI() { pintaps = 0; prevpin = ''; - updateBalance(); - - //change status var statusbox = ' Paid'; $("#invdisstatus").html(statusbox); @@ -3248,7 +3463,7 @@ function UI() { } else { $('#sendstdprogstatus').width('0%'); - $('#sendstdprognum').text('0%'); + $('#sendstdprognum').text('0%'); if (transactionid == "ErrInsufficientFunds") { $('#textMessageSendStd').text('Transaction Failed: Insufficient funds'); @@ -3277,306 +3492,407 @@ function UI() { } else { - //display pin error + $('.numdone').attr("style", "background-color:white"); + $("#sendstdpin").val(''); pintaps = 0; prevpin = ''; - $('#confpinalert').show(); - $('#confpinalertmess').text(ekey); - } + if (ekey.substring(0, 6) == "ErrPIN") { - }); + var attempts = ekey.substring(7, 8); - } + $("#pinconfcount").effect("shake"); + } else { - //INVOICE FUNCTIONS END------------------------------------------ + bootbox.alert(ekey); - function initialiseDashboard(callback) { + } - $("#dashsend").addClass("invis"); - $("#dashsend").removeClass("slideUp"); - $("#dashsend").hide(); - $("#dashreceive").addClass("invis"); - $("#dashreceive").removeClass("slideUp"); - $("#dashreceive").hide(); + } - $("#dashcontact").addClass("invis"); - $("#dashcontact").removeClass("slideUp"); - $("#dashcontact").hide(); + }); - $('#invoices').hide(); - $('#network').hide(); - //$('#networklist').hide(); - $("#networklistheader").hide(); - $('#settings').hide(); - $("#settingsheader").hide(); + } - var length = Engine.m_nickname.length; - if (length > 20) { - length = 20; - } - COINUNIT = Engine.m_settings.CoinUnit; + //INVOICE FUNCTIONS END------------------------------------------ - $("#mynickname").text(Engine.m_nickname); - $("#usernameProfile").text(Engine.m_nickname); - $("#mystatus").text(Engine.m_statusText); + function initialiseLocalSettings(callback) { - var imageSrc = "images/avatar/128px/Avatar-" + pad(length) + ".png"; - var imageSrcSmall = "images/avatar/64px/Avatar-" + pad(length) + ".png"; + //setup local settings + Engine.Device.getStorageItem("currency", function (res) { - if (Engine.m_profileImage != '') { - imageSrc = "https://ninkip2p.imgix.net/" + Engine.m_profileImage + "?crop=faces&fit=crop&h=128&w=128&mask=ellipse&border=1,d0d0d0"; - imageSrcSmall = "https://ninkip2p.imgix.net/" + Engine.m_profileImage + "?crop=faces&fit=crop&h=64&w=64&mask=ellipse&border=1,d0d0d0"; - } + if (res) { + Engine.m_settings.LocalCurrency = res; - $("#imgProfile").attr("src", imageSrc); - $("#imgtoprightprofile").attr("src", imageSrcSmall); + } else { - $("#codeForFriend").text(Engine.m_fingerprint); + Engine.Device.setStorageItem("currency", Engine.m_settings.LocalCurrency); + } + //console.log(Engine.m_settings.LocalCurrency); + //console.log(Engine.m_settings.CoinUnit); - Engine.getUserNetwork(function (err, friends) { + var t = Engine.m_settings.LocalCurrency; - FRIENDSLIST = {}; + $('.sccy').filter(function () { + return $(this).text().trim() == t; + }).find("label").html(''); - for (var i = 0; i < friends.length; i++) { - FRIENDSLIST[friends[i].userName] = friends[i]; - } - //prep the network tab - $("#networklist").show(); - //$("#networklistheader").show(); + Engine.Device.getStorageItem("coinunit", function (res) { - showTransactionFeed(function (err, res) { + if (res) { + Engine.m_settings.CoinUnit = res; - updateBalance(function (err, hasChanged) { + } else { - updatePrice(function () { + Engine.Device.setStorageItem("coinunit", Engine.m_settings.CoinUnit); + } - if (callback) { - callback(); + var tc = Engine.m_settings.CoinUnit; + $('.scoinunit').filter(function () { + return $(this).text().trim() == tc; + }).find("label").html(''); - } - }); + if (callback) { - }); + callback(); + + } + }); - updateUI(); - var data = Engine.m_fingerprint + ',' + Engine.m_nickname; - var options = { text: data, width: 172, height: 172 }; + }); - $('#fingerprintqr').text(''); - $('#fingerprintqr').qrcode(options); - $('#qrcontscan').text(''); - $('#qrcontscan').qrcode(options); + } - window.updateUIInterval = setInterval(function () { - updateUI(); + function updateProfile() { - }, 10000); + var length = Engine.m_nickname.length; + $("#usernameProfile").text(Engine.m_nickname); + $("#mystatus").text(Engine.m_statusText); - }); + var imageSrc = "images/avatar/128px/Avatar-" + pad(length) + ".png"; + var imageSrcSmall = "images/avatar/64px/Avatar-" + pad(length) + ".png"; - }); + if (Engine.m_profileImage != '') { + imageSrc = "https://ninkip2p.imgix.net/" + Engine.m_profileImage + "?crop=faces&fit=crop&h=128&w=128&mask=ellipse&border=1,d0d0d0"; + imageSrcSmall = "https://ninkip2p.imgix.net/" + Engine.m_profileImage + "?crop=faces&fit=crop&h=64&w=64&mask=ellipse&border=1,d0d0d0"; + } + $("#imgProfile").attr("src", imageSrc); } - function loadInvoices(callback) { - //load the invoices into the cache - //cachedInvoices = []; + function initialiseDashboardFromCache(callback) { - var tmpCachedInvoices = []; + $("#dashsend").addClass("invis"); + $("#dashsend").removeClass("slideUp"); + $("#dashsend").hide(); - Engine.getInvoiceList(function (err, invoices) { + $("#dashreceive").addClass("invis"); + $("#dashreceive").removeClass("slideUp"); + $("#dashreceive").hide(); - for (var i = 0; i < invoices.length; i++) { - var d1 = new Date(invoices[i].InvoiceDate); - invoices[i].JsDate = d1; - } + $("#dashcontact").addClass("invis"); + $("#dashcontact").removeClass("slideUp"); + $("#dashcontact").hide(); - invoices = _.sortBy(invoices, function (inv) { return -inv.JsDate; }); - for (var i = 0; i < invoices.length; i++) { + $('#invoices').hide(); + $('#network').hide(); + //$('#networklist').hide(); + $("#networklistheader").hide(); + $('#settings').hide(); + $("#settingsheader").hide(); - tmpCachedInvoices.push(invoices[i]); + var length = Engine.m_nickname.length; + if (length > 20) { + length = 20; + } - } - cachedInvoices = tmpCachedInvoices; + initialiseLocalSettings(function () { - var tmpCachedInvoicesByUser = []; + COINUNIT = Engine.m_settings.CoinUnit; + $("#mynickname").text(Engine.m_nickname); + $("#codeForFriend").text(Engine.m_fingerprint); - Engine.getInvoiceByUserList(function (err, invoices) { + //prep the network tab + $("#networklist").show(); - for (var i = 0; i < invoices.length; i++) { - var d1 = new Date(invoices[i].InvoiceDate); - invoices[i].JsDate = d1; - } + var data = Engine.m_fingerprint + ',' + Engine.m_nickname; + var options = { text: data, width: 172, height: 172 }; - invoices = _.sortBy(invoices, function (inv) { return -inv.JsDate; }); + $('#fingerprintqr').text(''); + $('#fingerprintqr').qrcode(options); + $('#qrcontscan').text(''); + $('#qrcontscan').qrcode(options); - for (var i = 0; i < invoices.length; i++) { - tmpCachedInvoicesByUser.push(invoices[i]); - } + window.updateUIInterval = setInterval(function () { - cachedInvoicesByUser = tmpCachedInvoicesByUser; + updateUI(); - if (callback) { - return callback(false, "ok"); - } + }, 10000); + + + window.updatePriceInterval = setInterval(function () { + + updatePrice(); + + }, 10000); + + + return callback("ok"); - }); }); } - function initialiseUI() { + function initialiseDashboard(callback) { - //updateFriends(function (err, res) { + $("#dashsend").addClass("invis"); + $("#dashsend").removeClass("slideUp"); + $("#dashsend").hide(); + $("#dashreceive").addClass("invis"); + $("#dashreceive").removeClass("slideUp"); + $("#dashreceive").hide(); + $("#dashcontact").addClass("invis"); + $("#dashcontact").removeClass("slideUp"); + $("#dashcontact").hide(); - //}); + $('#invoices').hide(); + $('#network').hide(); + //$('#networklist').hide(); + $("#networklistheader").hide(); + $('#settings').hide(); + $("#settingsheader").hide(); - } + var length = Engine.m_nickname.length; + if (length > 20) { + length = 20; + } + COINUNIT = Engine.m_settings.CoinUnit; - //OPEN/CREATE WALLET FUNCTIONS END--------------------------------------------- + $("#mynickname").text(Engine.m_nickname); + $("#usernameProfile").text(Engine.m_nickname); + $("#mystatus").text(Engine.m_statusText); - function pad(n) { - return (n < 10) ? ("0" + n) : n; - } - function logout() { - location.reload(); - } + var imageSrc = "images/avatar/128px/Avatar-" + pad(length) + ".png"; + var imageSrcSmall = "images/avatar/64px/Avatar-" + pad(length) + ".png"; - UI.updateUITimer = function () { - updateUI(); - }; + if (Engine.m_profileImage != '') { + imageSrc = "https://ninkip2p.imgix.net/" + Engine.m_profileImage + "?crop=faces&fit=crop&h=128&w=128&mask=ellipse&border=1,d0d0d0"; + imageSrcSmall = "https://ninkip2p.imgix.net/" + Engine.m_profileImage + "?crop=faces&fit=crop&h=64&w=64&mask=ellipse&border=1,d0d0d0"; + } - var prevBlock = 0; + $("#imgProfile").attr("src", imageSrc); + $("#imgtoprightprofile").attr("src", imageSrcSmall); - function updateUI(callback) { + $("#codeForFriend").text(Engine.m_fingerprint); - //All background UI activity controlled from here - //The focus is on minimizing any activity + //prep the network tab + $("#networklist").show(); + //$("#networklistheader").show(); - //get version - //checks all infra - //if error we have a problem + showTransactionFeed(function (err, res) { - var newBlock = false; + updateBalance(function (err, hasChanged) { - Engine.getVersion(function (err, res) { + updatePrice(function () { - if (!err) { + if (callback) { - var stats = JSON.parse(res); + callback(); - if (prevBlock != stats.BlockNumber) { - newBlock = true; - } + } - prevBlock = stats.BlockNumber; + }); + }); - if (stdAmountConvCoin) { - $('#stdselunit').text(COINUNIT); - } else { - $('#stdselunit').text(Engine.m_settings.LocalCurrency); - } + //updateUI(); + var data = Engine.m_fingerprint + ',' + Engine.m_nickname; + var options = { text: data, width: 172, height: 172 }; + $('#fingerprintqr').text(''); + $('#fingerprintqr').qrcode(options); + $('#qrcontscan').text(''); + $('#qrcontscan').qrcode(options); - $('#stdsendcunit').text(COINUNIT); - $('#stdsendlcurr').text(Engine.m_settings.LocalCurrency); + window.updateUIInterval = setInterval(function () { + updateUI(); - //Always + }, 10000); - updateBalance(function (err, hasChanged) { + window.updatePriceInterval = setInterval(function () { + updatePrice(); - //do we need to update transactions - //1. is our balance different from the last request? - //if it is immediately update transactions + }, 10000); - //2. do we have a new block? - //if so then call updatetransactions - //if (hasChanged || newBlock) { - //update transactions? + }); - showTransactionFeed(function (err, result) { + initialiseLocalSettings(); - loadInvoices(function (err, result) { + } - updateSelectedFriend(); + function loadInvoices(callback) { - }); + //load the invoices into the cache + //cachedInvoices = []; + var tmpCachedInvoices = []; + Engine.getInvoiceList(function (err, invoices) { - }); + for (var i = 0; i < invoices.length; i++) { + var d1 = new Date(invoices[i].InvoiceDate); + invoices[i].JsDate = d1; + } + + invoices = _.sortBy(invoices, function (inv) { return -inv.JsDate; }); + for (var i = 0; i < invoices.length; i++) { + + tmpCachedInvoices.push(invoices[i]); + } - updateFriendRequests(function (err, res) { + cachedInvoices = tmpCachedInvoices; + var tmpCachedInvoicesByUser = []; - }); + Engine.getInvoiceByUserList(function (err, invoices) { + + for (var i = 0; i < invoices.length; i++) { + var d1 = new Date(invoices[i].InvoiceDate); + invoices[i].JsDate = d1; + } + invoices = _.sortBy(invoices, function (inv) { return -inv.JsDate; }); - updateFriends(function (err, res) { + for (var i = 0; i < invoices.length; i++) { + tmpCachedInvoicesByUser.push(invoices[i]); + } + cachedInvoicesByUser = tmpCachedInvoicesByUser; + if (callback) { + return callback(false, "ok"); + } - }); + }); + }); + } - //update selected friend transactions also - //} + function initialiseUI() { - }); + //updateFriends(function (err, res) { - updatePrice(); + //}); - } + } - }); + //OPEN/CREATE WALLET FUNCTIONS END--------------------------------------------- + + function pad(n) { + return (n < 10) ? ("0" + n) : n; + } + + function logout() { + //location.reload(); + } + + + + + + var prevBlock = 0; + + function updateUI(callback) { + + if (stdAmountConvCoin) { + $('#stdselunit').text(COINUNIT); + } else { + $('#stdselunit').text(Engine.m_settings.LocalCurrency); + } + + $('#stdsendcunit').text(COINUNIT); + + $('#stdsendlcurr').text(Engine.m_settings.LocalCurrency); + + //Always + updateBalance(); + + showTransactionFeed(); + + updateSelectedFriend(); + + updateFriendRequests(); + + updateFriends(); + + } + + + function displayPrice(result) { + + result = _.escape(result); + price = result * 1.0; + + var loc = "en-US"; + var cprc = ""; + if (Engine.m_settings.LocalCurrency == "JPY" || Engine.m_settings.LocalCurrency == "CNY") { + cprc = accounting.formatMoney(result, "¥", 0); + } else if (Engine.m_settings.LocalCurrency == "GBP") { + cprc = accounting.formatMoney(result, "£", 2); + } else if (Engine.m_settings.LocalCurrency == "EUR") { + cprc = accounting.formatMoney(result, "€", 2); + } else if (Engine.m_settings.LocalCurrency == "USD") { + cprc = accounting.formatMoney(result, "$", 2); + } else if (Engine.m_settings.LocalCurrency == "CNY") { + cprc = accounting.formatMoney(result, "¥", 2); + } + $('#homeprice').html(cprc); } @@ -3586,32 +3902,18 @@ function UI() { //Always Ninki.API.getPrice(Engine.m_guid, Engine.m_settings.LocalCurrency, function (err, result) { + if (!err) { + + displayPrice(result); - result = _.escape(result); - price = result * 1.0; - - var loc = "en-US"; - var cprc = ""; - if (Engine.m_settings.LocalCurrency == "JPY" || Engine.m_settings.LocalCurrency == "CNY") { - cprc = accounting.formatMoney(result, "¥", 0); - } else if (Engine.m_settings.LocalCurrency == "GBP") { - cprc = accounting.formatMoney(result, "£", 2); - } else if (Engine.m_settings.LocalCurrency == "EUR") { - cprc = accounting.formatMoney(result, "€", 2); - } else if (Engine.m_settings.LocalCurrency == "USD") { - cprc = accounting.formatMoney(result, "$", 2); - } else if (Engine.m_settings.LocalCurrency == "CNY") { - cprc = accounting.formatMoney(result, "¥", 2); - } + Engine.Device.setStorageItem("price", price); - $('#homeprice').html(cprc); + } if (callback) { callback(); } - // + ' / BTC' - }); @@ -3690,29 +3992,47 @@ function UI() { if (balanceDisplayType == "coin") { balanceDisplayType = "currency"; - - - } else { balanceDisplayType = "coin"; - - } + var sbal = ""; if (balanceDisplayType == "coin") { var fbal = ''; if (COINUNIT == "BTC") { - fbal = accounting.formatMoney(currentBalance, "", 4); + fbal = accounting.formatMoney(currentBalance, "", 8); + + var enddec = fbal.slice(-4); + var chop = fbal.substring(0, fbal.length - 4); + fbal = chop; + + if ((enddec * 1) > 0) { + sbal = enddec; + } + } else if (COINUNIT == "Bits") { - fbal = accounting.formatMoney(currentBalance, "", 0); + + fbal = accounting.formatMoney(currentBalance, "", 2); + + var enddec = fbal.slice(-2); + var chop = fbal.substring(0, fbal.length - 3); + fbal = chop; + + if ((enddec * 1) > 0) { + sbal = '.' + enddec; + } + } else { fbal = accounting.formatMoney(currentBalance, "", 2); } $("#homebalance").text(fbal); + //$("#shomebalance").text(sbal); + $("#homecoinunit").text(COINUNIT); $("#calcbalance").text(fbal); + $("#scalcbalance").text(sbal); $("#calccoinunit").text(COINUNIT); } else { @@ -3720,13 +4040,14 @@ function UI() { var fbal = convertToLocalCurrency(currentBalance); + //$("#shomebalance").text(''); $("#homebalance").html(fbal); $("#homecoinunit").text(Engine.m_settings.LocalCurrency); + $("#scalcbalance").text(''); $("#calcbalance").html(fbal); $("#calccoinunit").text(Engine.m_settings.LocalCurrency); - } @@ -3735,69 +4056,101 @@ function UI() { }); - function updateBalance(callback) { - - Engine.getBalance(function (err, result) { + function displayBalance(data) { - if (!err) { + //get in units + var balance = convertFromSatoshis(data.TotalBalance, COINUNIT); - //get in units - var balance = convertFromSatoshis(result.TotalBalance, COINUNIT); + var sbal = ""; + if (balanceDisplayType == "coin") { + var fbal = ''; + if (COINUNIT == "BTC") { + fbal = accounting.formatMoney(balance, "", 8); - currentBalance = balance; + var enddec = fbal.slice(-4); + var chop = fbal.substring(0, fbal.length - 4); + fbal = chop; + if ((enddec * 1) > 0) { + sbal = enddec; + } - if (balanceDisplayType == "coin") { - var fbal = ''; - if (COINUNIT == "BTC") { - fbal = accounting.formatMoney(balance, "", 4); - } else if (COINUNIT == "Bits") { - fbal = accounting.formatMoney(balance, "", 0); - } else { - fbal = accounting.formatMoney(balance, "", 2); - } + } else if (COINUNIT == "Bits") { - $("#homebalance").text(fbal); - $("#homecoinunit").text(COINUNIT); + fbal = accounting.formatMoney(balance, "", 2); - $("#calcbalance").text(fbal); - $("#calccoinunit").text(COINUNIT); + var enddec = fbal.slice(-2); + var chop = fbal.substring(0, fbal.length - 3); + fbal = chop; - } else { + if ((enddec * 1) > 0) { + sbal = '.' + enddec; + } - var fbal = convertToLocalCurrency(balance); + } else { + fbal = accounting.formatMoney(balance, "", 2); + } - $("#homebalance").html(fbal); - $("#homecoinunit").text(Engine.m_settings.LocalCurrency); + $("#homebalance").text(fbal); + //$("#shomebalance").text(sbal); - $("#calcbalance").html(fbal); - $("#calccoinunit").text(Engine.m_settings.LocalCurrency); + $("#homecoinunit").text(COINUNIT); - } + $("#calcbalance").text(fbal); + $("#scalcbalance").text(sbal); + $("#calccoinunit").text(COINUNIT); + } else { + var fbal = convertToLocalCurrency(balance); - var template = ''; - if (result.UnconfirmedBalance > 0) { - template += ''; - } else { - template += ''; - } + //$("#shomebalance").text(''); + $("#homebalance").html(fbal); + $("#homecoinunit").text(Engine.m_settings.LocalCurrency); - var templatecalc = ''; - if (result.UnconfirmedBalance > 0) { - templatecalc += ''; - } else { - templatecalc += ''; - } + $("#scalcbalance").text(''); + $("#calcbalance").html(fbal); + $("#calccoinunit").text(Engine.m_settings.LocalCurrency); - $("#hometimer").html(template); - $("#calctimer").html(templatecalc); + } - if (previousBalance != result.TotalBalance || result.UnconfirmedBalance > 0) { + var template = ''; + if (data.UnconfirmedBalance > 0) { + template += ''; + } else { + template += ''; + } + + var templatecalc = ''; + if (data.UnconfirmedBalance > 0) { + templatecalc += ''; + } else { + templatecalc += ''; + } + + $("#hometimer").html(template); + $("#calctimer").html(templatecalc); + + } + + + function updateBalance(callback) { + + Engine.getBalance(function (err, result) { + + if (!err) { + + //get in units + var balance = convertFromSatoshis(result.TotalBalance, COINUNIT); + + currentBalance = balance; + + displayBalance(result); + + if (previousBalance != result.TotalBalance || result.UnconfirmedBalance > 0) { previousBalance = result.TotalBalance; @@ -3819,9 +4172,17 @@ function UI() { } + //cache the last balance result + + //var balcache = JSON.stringify(result); + //Engine.Device.setSecureStorageObject("balance", balcache, Engine.m_password, Engine.encrypt, ONE_HOUR); + + } else { - callback(true, "Error"); + if (callback) { + callback(true, "Error"); + } } @@ -3831,13 +4192,6 @@ function UI() { } - function updateNetwork() { - - // getNewFriends(); - //updateFriendRequests(); - getNewFriends(); - } - var previousReqByMe = 0; function updateRequestsMadeByMe(callback) { @@ -4159,7 +4513,7 @@ function UI() { function updateSelectedFriend(callback) { - //can optimise futher + //can optimise futhermnu norefresh = true; if (SELECTEDFRIEND.length > 0) { @@ -4222,7 +4576,7 @@ function UI() { $('#tblnetinvforme tbody').empty(); - + showTransactionNetwork(); lastInvoiceToPayNetCount = 0; lastInvoiceByMeNetCount = 0; @@ -4230,7 +4584,7 @@ function UI() { showInvoiceListNetwork(); showInvoiceByMeListNetwork(); - showTransactionNetwork(); + //$("#pnlfriend").show(); //$("#friendheader").show(); @@ -4261,90 +4615,89 @@ function UI() { Engine.getFriendRequests(function (err, ofriends) { - //if origin of friend request is qrcode - //and no phrase cache - //delay for 60 seconds - //add accept with scan button - //then return to standard after 5 minutes + if (!err) { + //if origin of friend request is qrcode + //and no phrase cache + //delay for 60 seconds + //add accept with scan button + //then return to standard after 5 minutes - var friends = []; - for (var i = 0; i < ofriends.length; i++) { + var friends = []; + for (var i = 0; i < ofriends.length; i++) { + + + //|| ofriends[i].ICanReceive + if (contactPhraseCache[ofriends[i].userName]) { + //acceptAndValidateFriend(ofriends[i].userName); + } else { + friends.push(ofriends[i]); + } - if (contactPhraseCache[ofriends[i].userName]) { - //acceptAndValidateFriend(ofriends[i].userName); - } else { - friends.push(ofriends[i]); } - } + if (friends.length > 0) { + $("#dashrequests").show(); - if (friends.length > 0) { - $("#dashrequests").show(); + } else { + $("#dashrequests").hide(); + } - } else { - $("#dashrequests").hide(); - } - //$("#notifications").text(friends.length); - //$("#notificationsright").text(friends.length); - //$("#nfriendreq").text(friends.length); + if (lastNoOfFriendsReq != friends.length || friends.length == 0) { - if (lastNoOfFriendsReq != friends.length || friends.length == 0) { + lastNoOfFriendsReq = friends.length; - lastNoOfFriendsReq = friends.length; + $("#friendreq").text(''); - if (friends.length > 0) { - $("#notifications").attr("class", "badge bg-danger pull-right"); - } else { - $("#notifications").attr("class", "badge pull-right"); - } - $("#nfriendreq").text(friends.length); - $("#friendreq").text(''); - for (var i = 0; i < friends.length; i++) { + for (var i = 0; i < friends.length; i++) { - var length = friends[i].userName.length; - if (length > 20) { - length = 20; - } + var length = friends[i].userName.length; + if (length > 20) { + length = 20; + } - var template = '
  • ' + + var template = '
  • ' + 'John said' + '' + '
  • '; - $("#friendreq").append(template); + $("#friendreq").append(template); - } + } - for (var i = 0; i < friends.length; i++) { + for (var i = 0; i < friends.length; i++) { - $("#friendreq #tapfriendreq" + i).hammer(null).bind("tap", { userName: friends[i].userName }, function (ev) { + $("#friendreq #tapfriendreq" + i).hammer(null).bind("tap", { userName: friends[i].userName }, function (ev) { - selectedFriendRequest = ev.data.userName; + selectedFriendRequest = ev.data.userName; - $("#friendrequestusername").text(selectedFriendRequest); + $("#friendrequestusername").text(selectedFriendRequest); - $("#mainWallet").hide(); - $("#networklistheader").hide(); - $(".footer").hide(); - $("#contactrequest").show(); + $("#mainWallet").hide(); + $("#networklistheader").hide(); + $(".footer").hide(); + $("#contactrequest").show(); - }); + }); + + } } + if (callback) { + callback(false, "done"); + } } - if (callback) { - callback(false, "done"); - } }); + + } $('#btnContactRequestClose').bind('touchstart', function () { @@ -4401,7 +4754,7 @@ function UI() { function showTransactionFeed(callback) { - Engine.getTransactionRecords(function (err, transactions) { + Engine.getTransactionFeed(function (err, transactions) { if (!err) { @@ -4442,9 +4795,9 @@ function UI() { var imageSrcSmall = "images/avatar/32px/Avatar-" + pad(length) + ".png"; if (transactions[i].UserName != 'External') { - if (FRIENDSLIST[transactions[i].UserName]) { - if (FRIENDSLIST[transactions[i].UserName].profileImage != '') { - imageSrcSmall = "https://ninkip2p.imgix.net/" + _.escape(FRIENDSLIST[transactions[i].UserName].profileImage) + "?crop=faces&fit=crop&h=128&w=128&mask=ellipse&border=1,d0d0d0"; + if (transactions[i].UserNameImage) { + if (transactions[i].UserNameImage != '') { + imageSrcSmall = "https://ninkip2p.imgix.net/" + _.escape(transactions[i].UserNameImage) + "?crop=faces&fit=crop&h=128&w=128&mask=ellipse&border=1,d0d0d0"; } } } @@ -4553,11 +4906,19 @@ function UI() { } - return callback(err, "ok"); + + //cache main screen items + //transaction list / price / balance + + if (callback) { + return callback(err, "ok"); + } } else { - return callback(err, transactions); + if (callback) { + return callback(err, transactions); + } } }); @@ -4568,116 +4929,118 @@ function UI() { function showTransactionNetwork(callback) { - var transactions = _.filter(transactionCache, function (tran) { return tran.UserName == SELECTEDFRIEND; }); + Engine.getTransactionsForNetwork(SELECTEDFRIEND, function (err, transactions) { - if (prevNetworkTransCount < transactions.length) { + if (prevNetworkTransCount < transactions.length) { - prevNetworkTransCount = transactions.length; + prevNetworkTransCount = transactions.length; - var template = ''; + var template = ''; - for (var i = 0; i < transactions.length; i++) { + for (var i = 0; i < transactions.length; i++) { - var amountLabel = ""; - var friendLabel = ""; + var amountLabel = ""; + var friendLabel = ""; - if (transactions[i].TransType == 'S') { - amountLabel = "sent " + formatCoinAmount(convertFromSatoshis(transactions[i].Amount, COINUNIT)) + " " + _.escape(COINUNIT); - friendLabel = "to " + _.escape(transactions[i].UserName); - } + if (transactions[i].TransType == 'S') { + amountLabel = "sent " + formatCoinAmount(convertFromSatoshis(transactions[i].Amount, COINUNIT)) + " " + _.escape(COINUNIT); + friendLabel = "to " + _.escape(transactions[i].UserName); + } - if (transactions[i].TransType == 'R') { - amountLabel = "received " + formatCoinAmount(convertFromSatoshis(transactions[i].Amount, COINUNIT)) + " " + _.escape(COINUNIT); - friendLabel = "from " + _.escape(transactions[i].UserName); - } + if (transactions[i].TransType == 'R') { + amountLabel = "received " + formatCoinAmount(convertFromSatoshis(transactions[i].Amount, COINUNIT)) + " " + _.escape(COINUNIT); + friendLabel = "from " + _.escape(transactions[i].UserName); + } - var trdate = new Date(transactions[i].TransDateTime.match(/\d+/)[0] * 1); - var timeLabel = prettydate.format(trdate); + var trdate = new Date(transactions[i].TransDateTime.match(/\d+/)[0] * 1); + var timeLabel = prettydate.format(trdate); - template += ''; - template += ''; + template += ''; + template += ''; - template += ''; - template += amountLabel; - template += ''; + template += ''; + template += amountLabel; + template += ''; - template += ''; - template += '
    '; - template += timeLabel; - template += '
    '; - template += '
    '; + template += ''; + template += '
    '; + template += timeLabel; + template += '
    '; + template += '
    '; - template += ''; - template += '
    '; - if (transactions[i].Confirmations < 6) { - template += ''; - template += _.escape(transactions[i].Confirmations); + template += ''; + template += '
    '; + if (transactions[i].Confirmations < 6) { + template += ''; + template += _.escape(transactions[i].Confirmations); + template += ''; + } + template += '
    '; + template += ''; + template += friendLabel; + template += ''; template += '
    '; + template += '
    '; + } - template += '
    '; - template += ''; - template += friendLabel; - template += ''; - template += ''; - template += ''; - } + $('#netpayfeed').html(template); - $('#netpayfeed').html(template); + for (var i = 0; i < transactions.length && i < 51; i++) { - for (var i = 0; i < transactions.length && i < 51; i++) { + $('#ntran' + i).hammer(null).bind("tap", { + index: i + }, function (event) { - $('#ntran' + i).hammer(null).bind("tap", { - index: i - }, function (event) { + if (!scrollingnettran) { - if (!scrollingnettran) { + displayTransactionDetails(transactions[event.data.index], "network"); - displayTransactionDetails(transactions[event.data.index], "network"); + } - } + }); + } - }); - } + } else { - } else { + $('#netpayfeed .conf').each(function (index, elem) { - $('#netpayfeed .conf').each(function (index, elem) { + var tran = allTransactions[transactionIndex[transactions[index].TransactionId]]; - var tran = allTransactions[transactionIndex[transactions[index].TransactionId]]; + var template = ''; + if (tran.Confirmations < 6) { + template += ''; + template += _.escape(tran.Confirmations); + template += ''; + } - var template = ''; - if (tran.Confirmations < 6) { - template += ''; - template += _.escape(tran.Confirmations); - template += ''; - } + $(elem).html(template); - $(elem).html(template); + //console.log('updating 1'); - //console.log('updating 1'); + }); - }); + $('#netpayfeed .trntime').each(function (index, elem) { - $('#netpayfeed .trntime').each(function (index, elem) { + var tran = allTransactions[transactionIndex[transactions[index].TransactionId]]; - var tran = allTransactions[transactionIndex[transactions[index].TransactionId]]; + var trdate = new Date(tran.TransDateTime.match(/\d+/)[0] * 1); - var trdate = new Date(tran.TransDateTime.match(/\d+/)[0] * 1); + var timeLabel = prettydate.format(trdate); - var timeLabel = prettydate.format(trdate); + $(elem).html(timeLabel); - $(elem).html(timeLabel); + //console.log('updating 2'); - //console.log('updating 2'); + }); - }); + } - } + }); } @@ -4813,9 +5176,9 @@ function UI() { prevNetworkTransCount = -1; prevtransfeed = -1; - showTransactionFeed(function (err, res) { - showTransactionNetwork(); - }); + showTransactionNetwork(); + showTransactionFeed(); + updateBalance(); sendAmount = ''; @@ -4950,7 +5313,6 @@ function UI() { prevtransfeed = -1; showTransactionFeed(); - updateUI(); sendAmount = ''; @@ -5279,6 +5641,9 @@ function UI() { $("#btnAcceptContactDone").hide(); $("#friendrequestp1").hide(); $("#friendrequestp2").show(); + + + $("#acceptcontactprognum").text('5%'); $("#acceptcontactprog").width('5%'); @@ -5312,24 +5677,26 @@ function UI() { if (!err) { - updateFriendRequests(function (err, result) { + $("#acceptcontactprognum").text('90%'); + $("#acceptcontactprog").width('90%'); - $("#acceptcontactprognum").text('90%'); - $("#acceptcontactprog").width('90%'); + setTimeout(function () { + $("#friendrequestusername").text(''); + $("#btnAcceptContactDone").show(); + $("#acceptcontactprogmess").text("You accepted the contact request from " + selectedFriendRequest); + $("#acceptcontactprognum").text('100%'); + $("#acceptcontactprog").width('100%'); + selectedFriendRequest = ''; + },500); - updateFriends(function (err, result) { - $("#friendrequestusername").text(''); - $("#btnAcceptContactDone").show(); - $("#acceptcontactprogmess").text("You accepted the contact request from " + selectedFriendRequest); - $("#acceptcontactprognum").text('100%'); - $("#acceptcontactprog").width('100%'); + updateFriendRequests(function (err, result) { + + updateFriends(function (err, result) { - selectedFriendRequest = ''; }); - }); } else { @@ -6000,5 +6367,1458 @@ function UI() { } + //loginPIN + //this function takes the user's input PIN number + //and authenticates the user + //if the user has not previosuly authenticated it downloads and decrypts + //all the relevant wallet data + var pinlock = false; + function loginPIN() { + + + var pin = $("#loginpinno").val(); + + $("#enterpinalert").hide(); + + if (pin.length == 4 && !pinlock) { + + pinlock = true; + + Engine.Device.getStorageItem("guid", function (guid) { + + + if (!Engine.m_appInitialised) { + + Engine.m_oguid = guid; + + 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) { + + //decrypt the passcode + //if no error the PIN is valid + if (!err) { + + if (!(typeof window.app === 'undefined')) { + app.isScanning = true; + } + + //is the app previosuly intialised + + if (Engine.m_appInitialised) { + + //if so simply change the UI state + //a session with the server has been established + + $('.numdone').attr("style", "background-color:white"); + + //check state and display correct headers + + + $("#paddel").hide(); + $('.numdone').attr("style", "background-color:white"); + $("#loginpin").hide(); + $("#pinloginmessage").text("Enter your PIN number"); + + $("#nonlogin").show(); + $("#loginpinno").val(''); + + pinlock = false; + + //do we show the footer or not? + + if ($("#footermode").val() == 1) { + $(".footer").show(); + } else { + $(".footer").hide(); + } + + //double check footer + //bug workaround + if (menustate == "profile" && profilepagestate == "") { + + $(".footer").show(); + + } + + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + $("#isactive").val(1); + + updateUI(); + + //refresh account settings in case they were updated + //in the chrome app + Engine.getAccountSettings(function (err, res) { + + if (!err) { + + //only set the settings we need to refresh for the mobile apps + var settingsObject = JSON.parse(res); + + Engine.m_settings.MinersFee = settingsObject.MinersFee; + Engine.m_settings.TwoFactor = settingsObject.TwoFactor; + Engine.m_settings.EmailVerified = settingsObject.EmailVerified; + + + if (!Engine.m_settings.EmailVerified) { + + + + $(".footer").hide(); + $('#dashheader').hide(); + $("#mainWallet").hide(); + $("#emailstep").show(); + + app.isScanning = true; + + + } + + } + + }); + + //refresh user profile data incase they updated + //it via the chrome app + Engine.getUserProfile(function (err, data) { + + data = JSON.parse(data); + + Engine.m_profileImage = data.ProfileImage; + Engine.m_statusText = data.Status; + + updateProfile(); + + }); + + + //refresh the UI state every 10 seconds + window.updateUIInterval = setInterval(function () { + + updateUI(); + + }, 10000); + + window.updatePriceInterval = setInterval(function () { + + updatePrice(); + + }, 10000); + + + + } else { + + + //disable keyboard scrolling in phone app + if (window.cordova) { + cordova.plugins.Keyboard.disableScroll(true); + } + + //first check for a cache + //this should be there after the first time a packet is intialised + Engine.Device.getStorageItem("dataCache", function (res) { + + if (res.length == 0) { + + //if the app has not been initialised then we need to download the wallet data + + $("#pairspinner").show(); + + var target = document.getElementById('pairspinner'); + var spinner = new Spinner(spinneropts).spin(target); + pinlock = false; + + $("#pinspinner").hide(); + $('.numdone').attr("style", "background-color:white"); + $("#loginpin").hide(); + $("#loginpinno").val(''); + + $("#paddel").hide(); + $("#pinloginmessage").text("Enter your PIN number"); + + + //get the encrypted user's password from local storage + Engine.Device.getSecureStorageObject("ninki_p", ekeyv.DeviceKey, Engine.decryptNp, function (result) { + + Engine.setStretchPass(result); + + //get the encrypted 2fa override token from local storage + Engine.Device.getSecureStorageObject("ninki_rem", ekeyv.DeviceKey, Engine.decryptNp, function (fatoken) { + + if (fatoken.length > 0) { + + + //use the token to open the wallet + Engine.openWallet(guid, fatoken, function (err, result) { + + if (!err) { + + //if this is true it means the 2fa token has expired + if (result.TwoFactorOnLogin) { + + $("#pairspinner").hide(); + $("#loginpinno").val(''); + pinlock = false; + //$("#enterpinalert").show(); + //$("#enterpinalertmessage").text('Token has expired'); + + bootbox.alert("Your token has expired. Please repair your device", function () { + + Engine.Device.deleteStorageItem("ninki_reg"); + Engine.Device.deleteStorageItem("ninki_p"); + Engine.Device.deleteStorageItem("ninki_rem"); + Engine.Device.deleteStorageItem("guid"); + + location.reload(); + + }); + + } else { + + + //create an encrypted cache to enable quick reloading of app state + + var dataToCache = Engine.serialize(); + + Engine.Device.setSecureStorageObject("dataCache", dataToCache, ekeyv.DeviceKey, Engine.encrypt); + + + //initilaise the UI elements + initialiseDashboard(function () { + + + Engine.m_appInitialised = true; + + $("#isactive").val(1); + + $("#pairspinner").hide(); + + $('#dashboard').show(); + $('#dashheader').show(); + + $("#mainWallet").show(); + $("#footermode").val(1); + $(".footer").show(); + + $("#nonlogin").show(); + + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + + }); + + + } + + } else { + + + if (result == "ErrLocked") { + + bootbox.alert("Your account is locked. Please unlock your account using the Chrome App"); + + } else { + + bootbox.alert(result); + + } + + pinlock = false; + + $("#pairspinner").hide(); + $('.numdone').attr("style", "background-color:white"); + $("#loginpin").show(); + $("#loginpinno").val(''); + $("#paddel").hide(); + $("#pinloginmessage").text("Enter your PIN number"); + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + } + + }); + + } + + }); + + }); + + } else { + + //initialise from cache + Engine.Device.getSecureStorageObject("dataCache", ekeyv.DeviceKey, Engine.decrypt, function (res) { + + + if (res != "") { + + Engine.initialize(JSON.parse(res)); + + var target = document.getElementById('pairspinner'); + var spinner = new Spinner(spinneropts).spin(target); + pinlock = false; + + $("#pairspinner").show(); + $("#pinspinner").hide(); + $('.numdone').attr("style", "background-color:white"); + $("#loginpin").hide(); + $("#loginpinno").val(''); + $("#paddel").hide(); + $("#pinloginmessage").text("Enter your PIN number"); + + + Engine.Device.getSecureStorageObject("ninki_p", ekeyv.DeviceKey, Engine.decryptNp, function (result) { + + //decrypt the password using the encryption key sent from the server + //and set the password + Engine.setStretchPass(result); + + //initilaise the UI elements + initialiseDashboardFromCache(function () { + + Engine.Device.getStorageItem("price", function (res) { + + displayPrice(JSON.parse(res)); + + }); + + + updateUI(); + + Engine.m_appInitialised = true; + + + + + $("#isactive").val(1); + + $("#pairspinner").hide(); + + $('#dashboard').show(); + $('#dashheader').show(); + + $("#mainWallet").show(); + $("#footermode").val(1); + $(".footer").show(); + + $("#nonlogin").show(); + + + + + + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + + //refresh account settings in case they were updated + //in the chrome app + Engine.getAccountSettings(function (err, res) { + + if (!err) { + + //only set the settings we need to refresh for the mobile apps + var settingsObject = JSON.parse(res); + + Engine.m_settings.MinersFee = settingsObject.MinersFee; + Engine.m_settings.TwoFactor = settingsObject.TwoFactor; + Engine.m_settings.EmailVerified = settingsObject.EmailVerified; + + if (!Engine.m_settings.EmailVerified) { + + $(".footer").hide(); + $('#dashheader').hide(); + $("#mainWallet").hide(); + $("#emailstep").show(); + + app.isScanning = true; + + + } + + } + + }); + + //refresh user profile data incase they updated + //it via the chrome app + Engine.getUserProfile(function (err, data) { + + data = JSON.parse(data); + + m_this.m_profileImage = data.ProfileImage; + m_this.m_statusText = data.Status; + + updateProfile(); + + }); + + + + }); + + }); + + } else { + + Engine.Device.deleteStorageItem("dataCache"); + //Engine.Device.deleteStorageItem("balance"); + bootbox.alert("Your cache has expired. Please try again.", function () { + + location.reload(); + + }); + } + + }); + } + + }); + + } + + } else { + + $("#pinspinner").hide(); + + if (ekeyv == "ErrDeviceDestroyed") { + + Engine.Device.deleteStorageItem("ninki_reg"); + Engine.Device.deleteStorageItem("ninki_p"); + Engine.Device.deleteStorageItem("ninki_rem"); + Engine.Device.deleteStorageItem("guid"); + + bootbox.alert("Too many failed attempts. The device has been unpaired.", function () { + + $("#loginpin").hide(); + $("#mainWallet").hide(); + $("#pairDevice").show(); + + location.reload(); + + }); + + } else { + + + pinlock = false; + + $("#loginpinno").val(''); + $('.numdone').attr("style", "background-color:white"); + $("#paddel").hide(); + + if (ekeyv.substring(0, 6) == "ErrPIN") { + + var attempts = ekeyv.substring(7, 8); + + $("#pinloginmessage").text("Incorrect PIN " + attempts + "/3 attempts"); + $("#pincounter").effect("shake"); + + } else { + + bootbox.alert(ekeyv); + + } + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + } + + } + + }); + + }); + + } else { + + $("#pinspinner").hide(); + + } + + } + + + + //device paring temp variables + var deviceName = ''; + var regToken = ''; + var secret = ''; + var enck = ''; + var iv = ''; + + //the user scans a QR code containing data encrypted with the server generated encryption key + + function pairDevice() { + + //disable keyboard scrolling on phone apps + if (window.cordova) { + cordova.plugins.Keyboard.disableScroll(true); + } + + $("#btnPairDevice").addClass("disabled"); + + var blob = $('#pairdeviceblob').val(); + var pwd = $('#pairpwd').val(); + + var splitBlob = blob.split('|'); + + + + //check for bad qr scan + if (splitBlob.length == 5) { + + + //flag that a scan is in progress so PIN + //screen does not show + + if (!(typeof window.app === 'undefined')) { + app.isScanning = true; + } + + var guid = splitBlob[2]; + + //encrypted hot key and 2fa override token + enck = splitBlob[0]; + iv = splitBlob[1]; + + //device name eg. My iPhone + deviceName = splitBlob[3]; + + //registration token for this pairing attempt + regToken = splitBlob[4]; + + //password enetered by the user + Engine.setPass(pwd, guid); + + 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) { + + if (err) { + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + + $("#btnPairDevice").removeClass("disabled"); + + bootbox.alert("There was an error, please try again."); + + + } else { + + //decrypt packet and set the secret + //the user will be asked next to choose a PIN + var jpacket = JSON.parse(response); + + secret = Engine.decryptNp(jpacket.packet, Engine.m_password, jpacket.IV); + + Engine.validateSecret(secret, function (err, secvalid) { + + if (!err) { + + if (secvalid) { + + //show pin screen + + $('#pairDevice').hide(); + $("#btnPairDevice").removeClass("disabled"); + $('#loginpin').show(); + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + } + + } else { + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + $("#btnPairDevice").removeClass("disabled"); + + if (secvalid == "ErrAccount") { + bootbox.alert("Password not correct"); + } else if (secvalid == "ErrLocked") { + bootbox.alert("The account is locked"); + } else { + bootbox.alert("There was an error, please try again"); + } + + } + + }); + + } + + }); + + } else { + + $("#btnPairDevice").removeClass("disabled"); + + bootbox.alert("There was a pairing error, please try again."); + + // $('#pairdevicealertmessage').text("There was a pairing error"); + //$('#pairdevicealert').show(); + } + + } + + + function regPIN() { + + //the user has chosen a PIN and can now register the deive with the server + + $("#pairspinner").show(); + + var target = document.getElementById('pairspinner'); + var spinner = new Spinner(spinneropts).spin(target); + + $('#loginpin').hide(); + + + if (!(typeof window.app === 'undefined')) { + app.isScanning = true; + } + + //hash the pin and device id + var deviceid = "DEVICE123456789"; + + if (window.cordova) { + deviceid = window.device.uuid; + } + + + //hash the PIN with the device id + //this is used to validate the PIN and lookup the encryption key on our server + + var pin = $("#loginpinno").val(); + + var pinhash = deviceid + pin; + bytes = []; + for (var i = 0; i < pinhash.length; ++i) { + bytes.push(pinhash.charCodeAt(i)); + } + + pinhash = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(bytes)).toString(); + + + //new register device + + + //enter password + //stretch + //get validate + //if valid + //choose a PIN + //register + + + var devplatform = "platform"; + var devmodel = "model"; + + if (window.cordova) { + devplatform = window.device.platform; + devmodel = window.device.model; + } + + //the device is registered with the server + //authentication via: + //generation of the pairing data required 2 factor authenticaton + // guid as an identifier + // registration token for this pairing session + //secret, which proves the user knows their password + //their chosen PIN number is registered with the server vi a hash of the PIN + Device uuid + //a 256 bit encryption key is generated on the server using a CSPRNG, this is used to encrypt data stored on the device + + Engine.registerDevice(Engine.m_guid, deviceName, devplatform, devmodel, pinhash, regToken, secret, function (err, result) { + + if (!err) { + + var dk = JSON.parse(result); + + if (dk.DeviceKey.length > 0) { + + //the server returns the encryption key + //whcih is used to decrypt the hotkey and 2fa override token + + var decblob = Engine.decryptNp(enck, dk.DeviceKey, iv); + + //slice it up + //64 64 + + + + var hk = ''; + var fatoken = ''; + + if (decblob.length == 96) { + hk = decblob.substring(0, 32); + fatoken = decblob.substring(32, 96); + } else { + hk = decblob.substring(0, 64); + fatoken = decblob.substring(64, 128); + } + + + //test opening the wallet + + Engine.openWallet(Engine.m_oguid, fatoken, function (err, result) { + + if (!err) { + + if (!result.TwoFactorOnLogin) { + + //if succesfull store the encrypted data in local storage + Engine.Device.setStorageItem("guid", Engine.m_oguid); + Engine.Device.setStorageItem("ninki_reg", regToken); + + Engine.Device.setSecureStorageObject("ninki_rem", fatoken, dk.DeviceKey, Engine.encryptNp); + Engine.Device.setSecureStorageObject("ninki_p", Engine.m_password, dk.DeviceKey, Engine.encryptNp); + Engine.Device.setSecureStorageObject("ninki_h", hk, dk.DeviceKey, Engine.encryptNp); + + var dataToCache = Engine.serialize(); + + Engine.Device.setSecureStorageObject("dataCache", dataToCache, dk.DeviceKey, Engine.encrypt); + + pinlock = false; + isPairing = false; + + //cache the main account data + + dk.DeviceKey = ''; + + + $("#loginpinno").val(''); + $("#paddel").hide(); + $('.numdone').attr("style", "background-color:white"); + + var t = Engine.m_settings.LocalCurrency; + + $('.sccy').filter(function () { + return $(this).text().trim() == t; + }).find("label").html(''); + + + var tc = Engine.m_settings.CoinUnit; + $('.scoinunit').filter(function () { + return $(this).text().trim() == tc; + }).find("label").html(''); + + + initialiseDashboard(function () { + + Engine.m_appInitialised = true; + + $("#pairspinner").hide(); + $('#dashboard').show(); + $('#dashheader').show(); + + $("#footermode").val(1); + $("#mainWallet").show(); + $(".footer").show(); + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + }); + + } else { + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + $("#pairspinner").hide(); + bootbox.alert("Could not pair", function () { + + location.reload(); + + }); + + } + + } else { + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + $("#pairspinner").hide(); + + bootbox.alert(result, function () { + + location.reload(); + + }); + + } + + }); + } else { + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + $("#pairspinner").hide(); + + bootbox.alert("The pairing token has expired", function () { + + location.reload(); + + }); + + } + + + } else { + + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + $("#pairspinner").hide(); + + bootbox.alert(result, function () { + + location.reload(); + + }); + + } + + }); + + secret = ''; + + } + + + + function regPINCreate() { + + //the user has chosen a PIN and can now register the deive with the server + + $("#pairspinner").show(); + var target = document.getElementById('pairspinner'); + var spinner = new Spinner(spinneropts).spin(target); + + $('#loginpin').hide(); + + + if (!(typeof window.app === 'undefined')) { + app.isScanning = true; + } + + //hash the pin and device id + var deviceid = "DEVICE123456789"; + + if (window.cordova) { + deviceid = window.device.uuid; + } + + + //hash the PIN with the device id + //this is used to validate the PIN and lookup the encryption key on our server + + var pin = $("#loginpinno").val(); + + var pinhash = deviceid + pin; + bytes = []; + for (var i = 0; i < pinhash.length; ++i) { + bytes.push(pinhash.charCodeAt(i)); + } + + pinhash = Bitcoin.Crypto.SHA256(Bitcoin.convert.bytesToWordArray(bytes)).toString(); + + + //new register device + + + //enter password + //stretch + //get validate + //if valid + //choose a PIN + //register + + + var devplatform = "platform"; + var devmodel = "model"; + + if (window.cordova) { + devplatform = window.device.platform; + devmodel = window.device.model; + } + + //the device is registered with the server + //authentication via: + //generation of the pairing data required 2 factor authenticaton + // guid as an identifier + // registration token for this pairing session + //secret, which proves the user knows their password + //their chosen PIN number is registered with the server vi a hash of the PIN + Device uuid + //a 256 bit encryption key is generated on the server using a CSPRNG, this is used to encrypt data stored on the device + + Engine.getRecoveryPacket(function (err, response) { + + if (err) { + + if (!(typeof window.app === 'undefined')) { + app.isScanning = false; + } + + $("#btnPairDevice").removeClass("disabled"); + + bootbox.alert("There was an error, please try again."); + + } else { + + //decrypt packet and set the secret + //the user will be asked next to choose a PIN + var jpacket = JSON.parse(response); + + secret = Engine.decryptNp(jpacket.packet, Engine.m_password, jpacket.IV); + + Engine.registerDevice(Engine.m_guid, deviceName, devplatform, devmodel, pinhash, regToken, secret, function (err, result) { + + if (!err) { + + var dk = JSON.parse(result); + + if (!(typeof window.app === 'undefined')) { + app.isScanning = true; + } + + Engine.Device.setStorageItem("guid", Engine.m_oguid); + + //test opening the wallet + + Engine.openWallet(Engine.m_oguid, fatoken, function (err, result) { + + if (!err) { + + if (!result.TwoFactorOnLogin) { + + //if succesfull store the encrypted data in local storage + + var dataToCache = Engine.serialize(); + Engine.Device.setSecureStorageObject("dataCache", dataToCache, dk.DeviceKey, Engine.encrypt); + + pinlock = false; + + $("#loginpinno").val(''); + $("#paddel").hide(); + $('.numdone').attr("style", "background-color:white"); + + var t = Engine.m_settings.LocalCurrency; + + $('.sccy').filter(function () { + return $(this).text().trim() == t; + }).find("label").html(''); + + + var tc = Engine.m_settings.CoinUnit; + $('.scoinunit').filter(function () { + return $(this).text().trim() == tc; + }).find("label").html(''); + + + isPairing = false; + + //callback here before displaying + + initialiseDashboard(function () { + + Engine.m_appInitialised = true; + + + //don't show main wallet yet + //show optional 2fa screen + + + $("#emailstep").show(); + + $("#pairspinner").hide(); + + $("#hotkeystep").hide(); + + isCreate = false; + + app.isScanning = true; + $("#isactive").val(1); + + + }); + + } else { + + //if (!(typeof window.app === 'undefined')) { + // app.isScanning = false; + //} + + $("#pairspinner").hide(); + bootbox.alert("Could not pair", function () { + + location.reload(); + + }); + + } + + } else { + + //if (!(typeof window.app === 'undefined')) { + // app.isScanning = false; + //} + + $("#pairspinner").hide(); + + bootbox.alert(result, function () { + + location.reload(); + + }); + + } + + }); + + + + } else { + + + //if (!(typeof window.app === 'undefined')) { + // app.isScanning = false; + //} + + $("#pairspinner").hide(); + bootbox.alert(result, function () { + + location.reload(); + + }); + + } + + }); + + } + + }); + + + + } + + + + + function closeSendNet() { + + $("#dashsend").addClass("invis"); + $("#dashsend").removeClass("slideUp"); + $("#dashsend").hide(); + + $("#dashsendamt").addClass("invis"); + $("#dashsendamt").removeClass("slideUp"); + $("#dashsendamt").hide(); + + $("#mainWallet").show(); + + if (sendmode == "net" || sendmode == "inv") { + $("#friendheader").show(); + } else { + $('#dashboard').show(); + $('#dashheader').show(); + + } + + $(".footer").show(); + + $("#dashreceive").addClass("invis"); + $("#dashreceive").removeClass("slideUp"); + $("#dashreceive").hide(); + + $("#dashcontact").addClass("invis"); + $("#dashcontact").removeClass("slideUp"); + $("#dashcontact").hide(); + + $("#pinconfirm").hide(); + + $("#btnStdSndDone").hide(); + + + $('#toAddress').val(''); + + sendAmount = ''; + + updateStdAmount(); + + } + + + function closeSendStd() { + + + $("#dashsend").removeClass("slideUp"); + $("#dashsend").addClass("invis"); + $("#dashsend").hide(); + + $("#dashsendamt").removeClass("slideUp"); + $("#dashsendamt").addClass("invis"); + $("#dashsendamt").hide(); + + $('#dashboard').show(); + $('#dashheader').show(); + + $("#mainWallet").show(); + $(".footer").show(); + + $("#dashreceive").removeClass("slideUp"); + $("#dashreceive").addClass("invis"); + $("#dashreceive").hide(); + + $("#dashcontact").removeClass("slideUp"); + $("#dashcontact").addClass("invis"); + $("#dashcontact").hide(); + + $("#pinconfirm").hide(); + + $("#btnStdSndDone").hide(); + + $('#toAddress').val(''); + + sendAmount = ''; + + updateStdAmount(); + + } + + var stdAmountConvCoin = true; + var netAmountConvCoin = true; + + function convertToLocalCurrency(amount) { + + var conv = amount; + conv = conv * 1.0; + + var sats = convertToSatoshis(conv, COINUNIT); + var btc = convertFromSatoshis(sats, "BTC"); + + var cbtc = btc * price; + + 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; + } + + var loc = "en-US"; + var cprc = ""; + if (Engine.m_settings.LocalCurrency == "JPY" || Engine.m_settings.LocalCurrency == "CNY") { + cprc = accounting.formatMoney(ires, "¥", 0); + } else if (Engine.m_settings.LocalCurrency == "GBP") { + cprc = accounting.formatMoney(ires, "£", 2); + } else if (Engine.m_settings.LocalCurrency == "EUR") { + cprc = accounting.formatMoney(ires, "€", 2); + } else if (Engine.m_settings.LocalCurrency == "USD") { + cprc = accounting.formatMoney(ires, "$", 2); + } else if (Engine.m_settings.LocalCurrency == "CNY") { + cprc = accounting.formatMoney(ires, "¥", 2); + } + + return cprc; + + } + + + function convertFromLocalCurrency(amount, format) { + + var conv = amount; + conv = conv * 1.0; + + + //convert to bitcoin + if (price > 0) { + var cbtc = conv / price; + + var sats = convertToSatoshis(cbtc, "BTC"); + + var dp = 4; + if (sats > 0 && sats < 10000) { + dp = 8; + } + + + var btc = convertFromSatoshis(sats, COINUNIT); + + + if (format) { + if (COINUNIT == "BTC") { + + btc = accounting.formatMoney(btc, "", dp); + + } + + if (COINUNIT == "Bits") { + + btc = accounting.formatMoney(btc, "", 0); + + } + } else { + + if (COINUNIT == "BTC") { + var dpr = 4; + if (sats > 0 && sats < 10000) { + dpr = 8; + } + + btc = accounting.toFixed(btc, dpr); + } + + if (COINUNIT == "Bits") { + var dpr = 0; + if (sats > 0 && sats < 10000) { + dpr = 2; + } + + btc = accounting.toFixed(btc, dpr); + } + } + + return btc; + + } else { + + return 0; + + } + + + } + + + var sendAmount = ''; + + function updateStdAmount() { + + //vamout will track the value + //hdamount.val is the value actually used as an + // input to the transaction + + + //if the input value is decimal . or empty + //set to 0 + + var vAmount = 0; + if (sendAmount == '' || sendAmount == '.') { + vAmount = 0; + } else { + vAmount = sendAmount; + } + + vAmount = vAmount * 1; + + if (sendAmount == '') { + + //default entry box and actual value in the case of no input + $('#amount').text('amount'); + if (stdAmountConvCoin) { + $('#ccystdamt').html(convertToLocalCurrency(0)); + } else { + $('#ccystdamt').html(convertFromLocalCurrency(0) + ' ' + COINUNIT); + } + $('#hdamount').val('0'); + + } else { + + if (stdAmountConvCoin) { + + //amounts are being input in a Bitcoin denomination + //so we convert to local currenct + + $('#ccystdamt').html(convertToLocalCurrency(vAmount)); + //convert bitcoin amount to number + $('#hdamount').val(vAmount * 1.0); + + var cprc = 0; + if (COINUNIT == "Bits") { + + //default bits to 0 decimal places + cprc = accounting.formatMoney(sendAmount, "", 0); + + } else { + + + var indot = sendAmount.indexOf('.'); + + //if the input is the beginning of input entry + //apply no formatting + if (sendAmount == '.' || sendAmount == '0.' || sendAmount == '0') { + + cprc = sendAmount; + + } + else if (indot == sendAmount.length - 1) { + //if the user has just enetered a decimal point + //format the number and add on the decimal for display + cprc = accounting.formatMoney(sendAmount, "", 0) + '.'; + } + else { + //if there is no decimal point apply formatting + //with 0 dp + if (indot == -1) { + + cprc = accounting.formatMoney(sendAmount, "", 0); + + } else { + + //allow bitcoin entry up to 8 decimal places + var ramt = Math.min(sendAmount.length - indot, 9); + ramt = ramt - 1; + cprc = accounting.formatMoney(sendAmount, "", ramt); + } + + } + + + } + + var fee = convertFromSatoshis(Engine.m_settings.MinersFee, COINUNIT); + var amountPlusFee = (vAmount + fee).toFixed(10); + + if ((currentBalance >= (amountPlusFee) && vAmount > 0) && convertToSatoshis(vAmount, COINUNIT) >= 10000) { + + $('#btnsendmoneystd').removeClass("disabled"); + + } else { + + $('#btnsendmoneystd').removeClass("disabled"); + $('#btnsendmoneystd').addClass("disabled"); + } + + $('#amount').text(cprc); + + } + else { + + //entry is in local currency + //so we need to convert to coin units and also format + //the currency input + + var amt = convertFromLocalCurrency(vAmount); + var amtfmt = convertFromLocalCurrency(vAmount, true); + amt = amt * 1.0; + + $('#hdamount').val(amt); + + $('#ccystdamt').text(amtfmt + ' ' + COINUNIT); + + var symb = ''; + if (Engine.m_settings.LocalCurrency == "JPY" || Engine.m_settings.LocalCurrency == "CNY") { + symb = "¥"; + } else if (Engine.m_settings.LocalCurrency == "GBP") { + symb = "£"; + } else if (Engine.m_settings.LocalCurrency == "EUR") { + symb = "€"; + } else if (Engine.m_settings.LocalCurrency == "USD") { + symb = "$"; + } else if (Engine.m_settings.LocalCurrency == "CNY") { + symb = "¥"; + } + + + var cprc = ''; + + var indot = sendAmount.indexOf('.'); + + if (sendAmount == '.' || sendAmount == '0.' || sendAmount == '0') { + + cprc = symb + sendAmount; + + } + else if (indot == sendAmount.length - 1) { + + cprc = accounting.formatMoney(sendAmount, symb, 0) + '.'; + } + else { + + if (indot == -1) { + + cprc = accounting.formatMoney(sendAmount, symb, 0); + + } else { + + var ramt = Math.min(sendAmount.length - indot, 2); + + cprc = symb + sendAmount + + } + + } + + var fee = convertFromSatoshis(Engine.m_settings.MinersFee, COINUNIT); + var amountPlusFee = (amt + fee).toFixed(10); + + if (currentBalance >= (amountPlusFee) && amt > 0 && convertToSatoshis(amt, COINUNIT) >= 10000) { + + $('#btnsendmoneystd').removeClass("disabled"); + + } else { + + $('#btnsendmoneystd').removeClass("disabled"); + $('#btnsendmoneystd').addClass("disabled"); + } + + + $('#amount').html(cprc); + } + } + + } + + } -module.exports = UI; \ No newline at end of file +module.exports = UI; diff --git a/src/ninki-ui.js b/src/ninki-ui.js index ede303b..38ef252 100644 --- a/src/ninki-ui.js +++ b/src/ninki-ui.js @@ -682,6 +682,7 @@ function UI() { $('#createWalletStart #cpassword').pwstrength(options); + var optionschng = {}; optionschng.ui = { container: "#newpwd-container", @@ -984,7 +985,7 @@ function UI() { var options = { text: data, width: 256, height: 256, ecLevel: 'H' }; - //$('#qrdevice').text(data); + $('#qrdevice').text(data); $('#qrdevice').qrcode(options); $('#pairqr2fa').hide(); @@ -1862,6 +1863,10 @@ function UI() { showTwoFactorQr(); } + }, function (message) { + + $("#textMessageCreate").text(message); + }); }