+ ${activeChain === 'XRP' ? html`
+
+
XRP-only login
+
You are logged in with an XRP private key. Only the XRP address is available.
+
+
+ My XRP (Ripple) address
+
+
+ ` : html`
BTC integrated with FLO
@@ -2839,16 +3395,95 @@
My FLO address
-
+
My Bitcoin address
-
+
My Ethereum address
-
+
+
+ My AVAX (Avalanche C-Chain) address
+
+
+
+ My BSC (Binance Smart Chain) address
+
+
+
+ My MATIC (Polygon) address
+
+
+
+ My ARB (Arbitrum) address
+
+
+
+ My OP (Optimism) address
+
+
+
+ My HBAR (Hedera) address
+
+
+
+ My XRP (Ripple) address
+
+
+
+ My SUI address
+
+
+
+ My TON address
+
+
+
+ My TRON address
+
+
+
+ My DOGE address
+
+
+
+ My LTC (Litecoin) address
+
+
+
+ My BCH (Bitcoin Cash) address
+
+
+
+ My DOT (Polkadot) address
+
+
+
+ My ALGO (Algorand) address
+
+
+
+ My XLM (Stellar) address
+
+
+
+ My SOL (Solana) address
+
+
+
+ My ADA (Cardano) address
+
+
+ ${(!floGlobals.myXrpID && floGlobals.isPrivKeySecured) ? html`
+
+ ` : ''}
+ `}
@@ -3086,6 +3721,14 @@
}
async function updateMessageUI(messagesData, sentByMe = false) {
+ const isSameAddrSafe = (a, b) => {
+ if (!a || !b) return false;
+ if (a === b) return true;
+ try {
+ return floCrypto.isSameAddr(a, b);
+ } catch (e) { return false; }
+ }
+
const animOptions = {
duration: 300,
easing: 'ease',
@@ -3095,8 +3738,8 @@
const { category, floID, time, message, sender, groupID, admin, name, pipeID, unconfirmed, type } = messagesData[messageId]
const chatAddress = floID || groupID || pipeID
// code to run if a chat is opened
- if (activeChat && floCrypto.isSameAddr(activeChat.address, chatAddress) || floCrypto.isSameAddr(floCrypto.getFloID(getEthPubKey(activeChat.address)), chatAddress)) {
- if (sentByMe || type === 'TRANSACTION' || !sender || !floCrypto.isSameAddr(sender, floDapps.user.id)) {
+ if (activeChat && (isSameAddrSafe(activeChat.address, chatAddress) || isSameAddrSafe(floCrypto.getFloID(getEthPubKey(activeChat.address)), chatAddress))) {
+ if (sentByMe || type === 'TRANSACTION' || !sender || !isSameAddrSafe(sender, floDapps.user.id)) {
const messageBody = render.messageBubble(messagesData[messageId]);
getRef('messages_container').append(messageBody);
}
@@ -3104,7 +3747,7 @@
scrollToBottom()
}
// remove encryption badge if it exists
- if (!groupID && (floDapps.user.get_pubKey(activeChat.address) || getEthPubKey(activeChat.address)) && floID !== floDapps.user.id) {
+ if (!groupID && (getContactPubKey(activeChat.address) || getEthPubKey(activeChat.address)) && floID !== floDapps.user.id) {
if (getRef('warn_no_encryption')) {
getRef('warn_no_encryption').after(
html.node`
@@ -3126,7 +3769,7 @@
}
// move chat card to top if it is not already there
const topChatCard = getRef('chats_list').children[0]
- if (!floCrypto.isSameAddr(chatAddress, topChatCard.dataset.address) && !floCrypto.isSameAddr(floCrypto.getFloID(getEthPubKey(chatAddress)), topChatCard.dataset.address)) {
+ if (!isSameAddrSafe(chatAddress, topChatCard.dataset.address) && !isSameAddrSafe(floCrypto.getFloID(getEthPubKey(chatAddress)), topChatCard.dataset.address)) {
const cloneContact = chatCard.cloneNode(true)
chatCard.remove()
getRef('chats_list').prepend(cloneContact)
@@ -3172,7 +3815,7 @@
if (chatCard.querySelector('.time'))
chatCard.querySelector('.time').textContent = getFormattedTime(time, 'relative')
- if (floCrypto.isSameAddr(activeChat.address, chatAddress) || floCrypto.isSameAddr(floCrypto.getFloID(getEthPubKey(activeChat.address)), chatAddress)) {
+ if (activeChat && (isSameAddrSafe(activeChat.address, chatAddress) || isSameAddrSafe(floCrypto.getFloID(getEthPubKey(activeChat.address)), chatAddress))) {
if (chatScrollInfo.isScrolledUp)
getRef('scroll_to_bottom').classList.add('new-message')
else {
@@ -3538,7 +4181,7 @@
const selctedPubKeys = [...selectedMembers].map(id => {
if (id === floDapps.user.id)
return floDapps.user.public
- return floDapps.user.get_pubKey(id)
+ return getContactPubKey(id)
});
const minRequired = parseInt(getRef('min_sign_required').value.trim());
const label = getRef('multisig_label').value.trim();
@@ -3826,19 +4469,31 @@
let addressToSave = getRef('add_contact_floID').value.trim();
let name = getRef('add_contact_name').value.trim();
if (floCrypto.isSameAddr(addressToSave, floDapps.user.id) || floCrypto.myEthID === addressToSave) {
- notify(`you can't add your own FLO/BTC/ETH address as contact`, 'error')
+ notify(`you can't add your own blockchain address as contact`, 'error')
return
}
if (floGlobals.contacts.hasOwnProperty(addressToSave)) {
notify(`Contact already saved`, 'error')
return
}
- // check whether an equivalent BTC/FLO address is already saved
- const addrInFlo = floCrypto.toFloID(addressToSave);
- const addrInBtc = btcOperator.convert.legacy2bech(addrInFlo);
- const addrInEth = floGlobals.pubKeys[addressToSave] ? floEthereum.ethAddressFromCompressedPublicKey(floGlobals.pubKeys[addressToSave]) : null;
- if (floGlobals.contacts.hasOwnProperty(addrInFlo) || floGlobals.contacts.hasOwnProperty(addrInBtc) || floGlobals.contacts.hasOwnProperty(addrInEth)) {
- notify(`Equivalent Address is already saved as ${getContactName(addrInFlo)}`, 'error');
+ // check whether an equivalent BTC/FLO address is already saved (only for compatible address types)
+ let addrInFlo = null, addrInBtc = null, addrInEth = null;
+ try {
+ // Only attempt conversion for legacy Base58 addresses (FLO/BTC format)
+ if ((addressToSave.length === 33 || addressToSave.length === 34) && /^[1-9A-HJ-NP-Za-km-z]+$/.test(addressToSave)) {
+ addrInFlo = floCrypto.toFloID(addressToSave);
+ if (addrInFlo) {
+ addrInBtc = btcOperator.convert.legacy2bech(addrInFlo);
+ }
+ }
+ addrInEth = floGlobals.pubKeys[addressToSave] ? floEthereum.ethAddressFromCompressedPublicKey(floGlobals.pubKeys[addressToSave]) : null;
+ } catch (e) {
+ // Conversion not applicable for this address type
+ }
+ if ((addrInFlo && floGlobals.contacts.hasOwnProperty(addrInFlo)) ||
+ (addrInBtc && floGlobals.contacts.hasOwnProperty(addrInBtc)) ||
+ (addrInEth && floGlobals.contacts.hasOwnProperty(addrInEth))) {
+ notify(`Equivalent Address is already saved as ${getContactName(addrInFlo || addressToSave)}`, 'error');
return;
}
rmMessenger.storeContact(addressToSave, name).then(result => {
@@ -3880,7 +4535,7 @@
}
for (const floID in floGlobals.contacts) {
if (getAddressType(floID) !== 'plain') continue;
- if (floDapps.user.get_pubKey(floID)) {
+ if (getContactPubKey(floID)) {
contacts.push(render.selectableContact(floID))
} else {
const hasSentRequest = skipSendingRequest.has(floID)
@@ -4012,12 +4667,19 @@
let floChatAddress
let btcChatAddress
const promises = []
- floChatAddress = validateEthAddress(address) ? floCrypto.getFloID(floGlobals.pubKeys[address] || getEthPubKey(address)) : floCrypto.toFloID(address);
+ // Safely try to derive FLO address (might fail for ADA/SOL etc)
+ try {
+ floChatAddress = validateEthAddress(address) ? floCrypto.getFloID(floGlobals.pubKeys[address] || getEthPubKey(address)) : floCrypto.toFloID(address);
+ } catch (e) { }
+
if (floChatAddress) {
btcChatAddress = btcOperator.convert.legacy2bech(floChatAddress);
promises.push(rmMessenger.getChat(floChatAddress), rmMessenger.getChat(btcChatAddress))
}
- if (validateEthAddress(address))
+
+ // Fetch chat for the address itself if it's not the derived FLO address
+ // This ensures we get messages for ADA, SOL, XRP etc.
+ if (address !== floChatAddress)
promises.push(rmMessenger.getChat(address))
Promise.all(promises)
.then((chats) => {
@@ -4043,7 +4705,8 @@
batchSize: 20,
onEnd: () => {
if (activeChat.type === 'plain') {
- if (floDapps.user.get_pubKey(activeChat.address) || getEthPubKey(activeChat.address)) {
+ const hasPubKey = getContactPubKey(activeChat.address) || getEthPubKey(activeChat.address);
+ if (hasPubKey) {
getRef('messages_container').prepend(html.node`
Conversation is encrypted
@@ -5282,4 +5945,4 @@