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 = '' +
'' +
'' +
'';
- $("#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);
+
});
}