added option to set password
This commit is contained in:
parent
2e753968b8
commit
6bff6c476b
30
index.html
30
index.html
@ -788,6 +788,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<sm-button class="danger justify-self-start" onclick="signOut()">Sign out</sm-button>
|
<sm-button class="danger justify-self-start" onclick="signOut()">Sign out</sm-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid gap-1 card">
|
||||||
|
<h4>Secure private key</h4>
|
||||||
|
<p>
|
||||||
|
You can set a password to secure your private key and use the password instead of private key.
|
||||||
|
This is applied to this browser only.
|
||||||
|
</p>
|
||||||
|
<button id="secure_pwd_button" class="button button--primary justify-self-start secure-priv-key"
|
||||||
|
onclick="openPopup('secure_pwd_popup')">Set
|
||||||
|
password</button>
|
||||||
|
</div>
|
||||||
<div class="grid gap-1 user-element card">
|
<div class="grid gap-1 user-element card">
|
||||||
<h4>My UPI IDs</h4>
|
<h4>My UPI IDs</h4>
|
||||||
<ul id="saved_upi_ids_list" class="observe-empty-state"></ul>
|
<ul id="saved_upi_ids_list" class="observe-empty-state"></ul>
|
||||||
@ -1434,6 +1444,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</sm-popup>
|
</sm-popup>
|
||||||
|
<sm-popup id="secure_pwd_popup">
|
||||||
|
<header slot="header" class="popup__header">
|
||||||
|
<button class="popup__header__close justify-self-start">
|
||||||
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
|
fill="#000000">
|
||||||
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<h3 id="secure_pwd_title">Set password</h3>
|
||||||
|
</header>
|
||||||
|
<sm-form>
|
||||||
|
<sm-input id="secure_pwd_input" type="password" placeholder="Password" animate required autofocus>
|
||||||
|
</sm-input>
|
||||||
|
<button class="button button--primary cta secure-priv-key" type="submit" onclick="setSecurePassword()">
|
||||||
|
Set
|
||||||
|
</button>
|
||||||
|
</sm-form>
|
||||||
|
</sm-popup>
|
||||||
|
|
||||||
<!-- Cashier popups -->
|
<!-- Cashier popups -->
|
||||||
<sm-popup id="confirm_topup_popup">
|
<sm-popup id="confirm_topup_popup">
|
||||||
|
|||||||
@ -1117,13 +1117,13 @@ customElements.define('sm-notifications', class extends HTMLElement {
|
|||||||
|
|
||||||
createNotification(message, options = {}) {
|
createNotification(message, options = {}) {
|
||||||
const { pinned = false, icon = '', action } = options;
|
const { pinned = false, icon = '', action } = options;
|
||||||
const notification = document.createElement('output')
|
const notification = document.createElement('div')
|
||||||
notification.id = this.randString(8)
|
notification.id = this.randString(8)
|
||||||
notification.classList.add('notification');
|
notification.classList.add('notification');
|
||||||
let composition = ``;
|
let composition = ``;
|
||||||
composition += `
|
composition += `
|
||||||
<div class="icon-container">${icon}</div>
|
<div class="icon-container">${icon}</div>
|
||||||
<p>${message}</p>
|
<output>${message}</output>
|
||||||
`;
|
`;
|
||||||
if (action) {
|
if (action) {
|
||||||
composition += `
|
composition += `
|
||||||
@ -1177,6 +1177,7 @@ customElements.define('sm-notifications', class extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeNotification(notification, direction = 'left') {
|
removeNotification(notification, direction = 'left') {
|
||||||
|
if (!notification) return;
|
||||||
const sign = direction === 'left' ? '-' : '+';
|
const sign = direction === 'left' ? '-' : '+';
|
||||||
notification.animate([
|
notification.animate([
|
||||||
{
|
{
|
||||||
@ -1218,8 +1219,10 @@ customElements.define('sm-notifications', class extends HTMLElement {
|
|||||||
|
|
||||||
this.mediaQuery.addEventListener('change', this.handleOrientationChange);
|
this.mediaQuery.addEventListener('change', this.handleOrientationChange);
|
||||||
this.notificationPanel.addEventListener('pointerdown', e => {
|
this.notificationPanel.addEventListener('pointerdown', e => {
|
||||||
if (e.target.closest('.notification')) {
|
if (e.target.closest('.close')) {
|
||||||
this.swipeThreshold = this.clientWidth / 2;
|
this.removeNotification(e.target.closest('.notification'));
|
||||||
|
} else if (e.target.closest('.notification')) {
|
||||||
|
this.swipeThreshold = e.target.closest('.notification').getBoundingClientRect().width / 2;
|
||||||
this.currentTarget = e.target.closest('.notification');
|
this.currentTarget = e.target.closest('.notification');
|
||||||
this.currentTarget.setPointerCapture(e.pointerId);
|
this.currentTarget.setPointerCapture(e.pointerId);
|
||||||
this.startTime = Date.now();
|
this.startTime = Date.now();
|
||||||
@ -1262,12 +1265,6 @@ customElements.define('sm-notifications', class extends HTMLElement {
|
|||||||
this.notificationPanel.releasePointerCapture(e.pointerId);
|
this.notificationPanel.releasePointerCapture(e.pointerId);
|
||||||
this.currentX = 0;
|
this.currentX = 0;
|
||||||
});
|
});
|
||||||
this.notificationPanel.addEventListener('click', e => {
|
|
||||||
if (e.target.closest('.close')) {
|
|
||||||
this.removeNotification(e.target.closest('.notification'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const observer = new MutationObserver(mutationList => {
|
const observer = new MutationObserver(mutationList => {
|
||||||
mutationList.forEach(mutation => {
|
mutationList.forEach(mutation => {
|
||||||
if (mutation.type === 'childList') {
|
if (mutation.type === 'childList') {
|
||||||
|
|||||||
156
scripts/fn_ui.js
156
scripts/fn_ui.js
@ -11,9 +11,16 @@
|
|||||||
const relativeTime = new RelativeTime({ style: 'narrow' });
|
const relativeTime = new RelativeTime({ style: 'narrow' });
|
||||||
|
|
||||||
// use floDapps.storeContact() to store contacts that can be used by other apps on same device
|
// use floDapps.storeContact() to store contacts that can be used by other apps on same device
|
||||||
function syncUserData(obsName, data) {
|
async function syncUserData(obsName, data) {
|
||||||
const dataToSend = Crypto.AES.encrypt(JSON.stringify(data), myPrivKey);
|
floDapps.user.private.then(privateKey => {
|
||||||
return floCloudAPI.sendApplicationData(dataToSend, obsName, { receiverID: floDapps.user.id });
|
if (!privateKey) return;
|
||||||
|
const encryptedData = Crypto.AES.encrypt(JSON.stringify(data), privateKey);
|
||||||
|
return floCloudAPI.sendApplicationData(encryptedData, obsName, { receiverID: floDapps.user.id });
|
||||||
|
}).catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
notify('Invalid password', 'error');
|
||||||
|
return false;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
// store user data in separate IDB
|
// store user data in separate IDB
|
||||||
async function organizeSyncedData(obsName) {
|
async function organizeSyncedData(obsName) {
|
||||||
@ -21,13 +28,20 @@ async function organizeSyncedData(obsName) {
|
|||||||
if (fetchedData.length && await compactIDB.readData(obsName, 'lastSyncTime') !== fetchedData[0].time) {
|
if (fetchedData.length && await compactIDB.readData(obsName, 'lastSyncTime') !== fetchedData[0].time) {
|
||||||
await compactIDB.clearData(obsName);
|
await compactIDB.clearData(obsName);
|
||||||
const dataToDecrypt = floCloudAPI.util.decodeMessage(fetchedData[0].message);
|
const dataToDecrypt = floCloudAPI.util.decodeMessage(fetchedData[0].message);
|
||||||
const decryptedData = JSON.parse(Crypto.AES.decrypt(dataToDecrypt, myPrivKey));
|
floDapps.user.private.then(privateKey => {
|
||||||
for (let key in decryptedData) {
|
if (!privateKey) return;
|
||||||
floGlobals[obsName][key] = decryptedData[key];
|
const decryptedData = JSON.parse(Crypto.AES.decrypt(dataToDecrypt, privateKey));
|
||||||
compactIDB.addData(obsName, decryptedData[key], key);
|
for (let key in decryptedData) {
|
||||||
}
|
floGlobals[obsName][key] = decryptedData[key];
|
||||||
compactIDB.addData(obsName, fetchedData[0].time, 'lastSyncTime');
|
compactIDB.addData(obsName, decryptedData[key], key);
|
||||||
return true;
|
}
|
||||||
|
compactIDB.addData(obsName, fetchedData[0].time, 'lastSyncTime');
|
||||||
|
return true;
|
||||||
|
}).catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
notify('Invalid password', 'error');
|
||||||
|
return false;
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
const idbData = await compactIDB.readAllData(obsName);
|
const idbData = await compactIDB.readAllData(obsName);
|
||||||
for (const key in idbData) {
|
for (const key in idbData) {
|
||||||
@ -121,22 +135,30 @@ function withdrawMoneyFromWallet() {
|
|||||||
function transferToExchange() {
|
function transferToExchange() {
|
||||||
const amount = parseFloat(getRef('exchange_transfer__amount').value.trim());
|
const amount = parseFloat(getRef('exchange_transfer__amount').value.trim());
|
||||||
buttonLoader('exchange_transfer__button', true);
|
buttonLoader('exchange_transfer__button', true);
|
||||||
floExchangeAPI.depositToken('rupee', amount, floDapps.user.id, 'FRJkPqdbbsug3TtQRAWviqvTL9Qr2EMnrm', myPrivKey).then(txid => {
|
floDapps.user.private.then(privateKey => {
|
||||||
console.log(txid);
|
if (!privateKey) return;
|
||||||
showChildElement('exchange_transfer_process', 1);
|
floExchangeAPI.depositToken('rupee', amount, floDapps.user.id, 'FRJkPqdbbsug3TtQRAWviqvTL9Qr2EMnrm', privateKey).then(txid => {
|
||||||
getRef('exchange_transfer__success_message').textContent = `Transferred ${formatAmount(amount)} to exchange`;
|
console.log(txid);
|
||||||
}).catch(error => {
|
showChildElement('exchange_transfer_process', 1);
|
||||||
|
getRef('exchange_transfer__success_message').textContent = `Transferred ${formatAmount(amount)} to exchange`;
|
||||||
|
}).catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
if (error.code) {
|
||||||
|
error = error.message;
|
||||||
|
}
|
||||||
|
if (error === 'Insufficient rupee# balance')
|
||||||
|
error = 'Insufficient rupee token balance in your wallet, please top-up your wallet.';
|
||||||
|
getRef('exchange_transfer__failed_reason').textContent = error;
|
||||||
|
showChildElement('exchange_transfer_process', 2);
|
||||||
|
}).finally(() => {
|
||||||
|
buttonLoader('exchange_transfer__button', false);
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
if (error.code) {
|
notify('Invalid password', 'error');
|
||||||
error = error.message;
|
closePopup();
|
||||||
}
|
return false;
|
||||||
if (error === 'Insufficient rupee# balance')
|
})
|
||||||
error = 'Insufficient rupee token balance in your wallet, please top-up your wallet.';
|
|
||||||
getRef('exchange_transfer__failed_reason').textContent = error;
|
|
||||||
showChildElement('exchange_transfer_process', 2);
|
|
||||||
}).finally(() => {
|
|
||||||
buttonLoader('exchange_transfer__button', false);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function renderSavedUpiIds() {
|
async function renderSavedUpiIds() {
|
||||||
@ -470,12 +492,13 @@ function declineTopUp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function completeTokenToCashRequest(request) {
|
async function completeTokenToCashRequest(request) {
|
||||||
const { vectorClock, senderID, message: { token_txid, amount, upi_id } } = request;
|
const { vectorClock, senderID, message: { token_txid, amount, upi_id } } = request;
|
||||||
var upiID;
|
var upiID;
|
||||||
if (upi_id instanceof Object && "secret" in upi_id) {
|
if (upi_id instanceof Object && "secret" in upi_id) {
|
||||||
try {
|
try {
|
||||||
upiID = floCrypto.decryptData(upi_id, myPrivKey);
|
const privateKey = await floGlobals.user.private
|
||||||
|
upiID = floCrypto.decryptData(upi_id, privateKey);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("UPI ID is not encrypted with a proper key", error);
|
console.error("UPI ID is not encrypted with a proper key", error);
|
||||||
return notify("Invalid UPI ID", 'error');
|
return notify("Invalid UPI ID", 'error');
|
||||||
@ -1197,17 +1220,26 @@ function getSignedIn(passwordType) {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
console.log(floDapps.user.id)
|
console.log(floDapps.user.id)
|
||||||
|
getPromptInput('Enter password', '', {
|
||||||
|
isPassword: true,
|
||||||
|
}).then(password => {
|
||||||
|
if (password) {
|
||||||
|
resolve(password)
|
||||||
|
}
|
||||||
|
})
|
||||||
}catch(err) {
|
}catch(err) {
|
||||||
if (passwordType === 'PIN/Password') {
|
if (passwordType === 'PIN/Password') {
|
||||||
|
floGlobals.isPrivKeySecured = true;
|
||||||
getRef('private_key_field').removeAttribute('data-private-key');
|
getRef('private_key_field').removeAttribute('data-private-key');
|
||||||
getRef('private_key_field').setAttribute('placeholder', 'Password');
|
getRef('private_key_field').setAttribute('placeholder', 'Password');
|
||||||
getRef('private_key_field').customValidation = null
|
getRef('private_key_field').customValidation = null
|
||||||
|
getRef('secure_pwd_button').closest('.card').classList.add('hidden');
|
||||||
} else {
|
} else {
|
||||||
|
floGlobals.isPrivKeySecured = false;
|
||||||
getRef('private_key_field').dataset.privateKey = ''
|
getRef('private_key_field').dataset.privateKey = ''
|
||||||
getRef('private_key_field').setAttribute('placeholder', 'FLO private key');
|
getRef('private_key_field').setAttribute('placeholder', 'FLO private key');
|
||||||
getRef('private_key_field').customValidation = floCrypto.getPubKeyHex
|
getRef('private_key_field').customValidation = floCrypto.getPubKeyHex;
|
||||||
|
getRef('secure_pwd_button').closest('.card').classList.remove('hidden');
|
||||||
}
|
}
|
||||||
if (window.location.hash.includes('sign_in') || window.location.hash.includes('sign_up')) {
|
if (window.location.hash.includes('sign_in') || window.location.hash.includes('sign_up')) {
|
||||||
showPage(window.location.hash);
|
showPage(window.location.hash);
|
||||||
@ -1227,6 +1259,19 @@ function getSignedIn(passwordType) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function setSecurePassword() {
|
||||||
|
if (!floGlobals.isPrivKeySecured) {
|
||||||
|
const password = getRef('secure_pwd_input').value.trim();
|
||||||
|
floDapps.securePrivKey(password).then(() => {
|
||||||
|
floGlobals.isPrivKeySecured = true;
|
||||||
|
notify('Password set successfully', 'success');
|
||||||
|
getRef('secure_pwd_button').closest('.card').classList.add('hidden');
|
||||||
|
closePopup();
|
||||||
|
}).catch(err => {
|
||||||
|
notify(err, 'error');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
function signOut() {
|
function signOut() {
|
||||||
getConfirmation('Sign out?', 'You are about to sign out of the app, continue?', 'Stay', 'Leave')
|
getConfirmation('Sign out?', 'You are about to sign out of the app, continue?', 'Stay', 'Leave')
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
@ -1372,31 +1417,38 @@ getRef('fees_selector').addEventListener('change', e => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
getRef('send_transaction').onclick = evt => {
|
getRef('send_transaction').onclick = evt => {
|
||||||
buttonLoader('send_transaction', true)
|
buttonLoader('send_transaction', true)
|
||||||
const senders = btc_api.convert.legacy2bech(floDapps.user.id);
|
floGlobals.user.private.then(privateKey => {
|
||||||
const privKeys = btc_api.convert.wif(myPrivKey);
|
const privKeys = btc_api.convert.wif(privateKey);
|
||||||
const receivers = [...getRef('receiver_container').querySelectorAll('.receiver-input')].map(input => input.value.trim());
|
const senders = btc_api.convert.legacy2bech(floDapps.user.id);
|
||||||
const amounts = [...getRef('receiver_container').querySelectorAll('.amount-input')].map(input => {
|
const receivers = [...getRef('receiver_container').querySelectorAll('.receiver-input')].map(input => input.value.trim());
|
||||||
return parseFloat(input.value.trim())
|
const amounts = [...getRef('receiver_container').querySelectorAll('.amount-input')].map(input => {
|
||||||
});
|
return parseFloat(input.value.trim())
|
||||||
const fee = parseFloat(getRef('send_fee').value.trim());
|
});
|
||||||
console.debug(senders, receivers, amounts, fee);
|
const fee = parseFloat(getRef('send_fee').value.trim());
|
||||||
btc_api.sendTx(senders, privKeys, receivers, amounts, fee).then(result => {
|
console.debug(senders, receivers, amounts, fee);
|
||||||
console.log(result);
|
btc_api.sendTx(senders, privKeys, receivers, amounts, fee).then(result => {
|
||||||
closePopup();
|
console.log(result);
|
||||||
getRef('txid').value = result.txid;
|
closePopup();
|
||||||
openPopup('txid_popup');
|
getRef('txid').value = result.txid;
|
||||||
getRef('send_tx').reset()
|
openPopup('txid_popup');
|
||||||
getExchangeRate().then(() => {
|
getRef('send_tx').reset()
|
||||||
calculateBtcFees()
|
getExchangeRate().then(() => {
|
||||||
}).catch(e => {
|
calculateBtcFees()
|
||||||
console.error(e)
|
}).catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
})
|
||||||
|
}).catch(error => {
|
||||||
|
notify(`Error sending transaction \n ${error}`, 'error');
|
||||||
|
}).finally(_ => {
|
||||||
|
buttonLoader('send_transaction', false)
|
||||||
})
|
})
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
notify(`Error sending transaction \n ${error}`, 'error');
|
console.log(error);
|
||||||
}).finally(_ => {
|
notify('Invalid password', 'error');
|
||||||
buttonLoader('send_transaction', false)
|
closePopup();
|
||||||
|
return false;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -134,6 +134,7 @@ document.addEventListener('popupclosed', e => {
|
|||||||
break;
|
break;
|
||||||
case 'transfer_to_exchange_popup':
|
case 'transfer_to_exchange_popup':
|
||||||
showChildElement('exchange_transfer_process', 0);
|
showChildElement('exchange_transfer_process', 0);
|
||||||
|
buttonLoader('exchange_transfer__button', false);
|
||||||
break;
|
break;
|
||||||
case 'confirm_topup_popup':
|
case 'confirm_topup_popup':
|
||||||
showChildElement('confirm_topup_wrapper', 0);
|
showChildElement('confirm_topup_wrapper', 0);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user