feat: Add Ripple (XRP) private key validation and decoding
This commit is contained in:
parent
b61209902a
commit
9349aaf48a
119
index.html
119
index.html
@ -78,37 +78,62 @@
|
||||
document.body.prepend(document.createElement('adblocker-warning'))
|
||||
return
|
||||
}
|
||||
floGlobals.myFloID = floCrypto.getFloID(floDapps.user.public);
|
||||
floGlobals.myBtcID = btcOperator.convert.legacy2bech(floGlobals.myFloID)
|
||||
floGlobals.myEthID = floEthereum.ethAddressFromCompressedPublicKey(floDapps.user.public)
|
||||
// AVAX C-Chain uses same address format as Ethereum
|
||||
floGlobals.myAvaxID = floGlobals.myEthID;
|
||||
// BSC (Binance Smart Chain) uses same address format as Ethereum
|
||||
floGlobals.myBscID = floGlobals.myEthID;
|
||||
// MATIC (Polygon) uses same address format as Ethereum
|
||||
floGlobals.myMaticID = floGlobals.myEthID;
|
||||
// Arbitrum uses same address format as Ethereum
|
||||
floGlobals.myArbID = floGlobals.myEthID;
|
||||
// Optimism uses same address format as Ethereum
|
||||
floGlobals.myOpID = floGlobals.myEthID;
|
||||
// HBAR (Hedera) uses same address format as Ethereum
|
||||
floGlobals.myHbarID = floGlobals.myEthID;
|
||||
|
||||
// Initialize private-key-dependent addresses to null (will be derived after messenger init)
|
||||
floGlobals.myXrpID = null;
|
||||
floGlobals.mySuiID = null;
|
||||
floGlobals.myAdaID = null;
|
||||
floGlobals.myTonID = null;
|
||||
floGlobals.myTronID = null;
|
||||
floGlobals.myDogeID = null;
|
||||
floGlobals.myLtcID = null;
|
||||
floGlobals.myBchID = null;
|
||||
floGlobals.myDotID = null;
|
||||
floGlobals.myAlgoID = null;
|
||||
floGlobals.myXlmID = null;
|
||||
floGlobals.mySolID = null;
|
||||
// Note: Cardano (ADA) address will be derived from private key later
|
||||
let activeChain = localStorage.getItem(`${floGlobals.application}#activeChain`);
|
||||
if (activeChain === 'XRP') {
|
||||
// XRP-only login: skip FLO/BTC/ETH derivations
|
||||
floGlobals.myFloID = floDapps.user.id; // This is the XRP address (r...)
|
||||
floGlobals.myXrpID = floDapps.user.id;
|
||||
floGlobals.myBtcID = null;
|
||||
floGlobals.myEthID = null;
|
||||
floGlobals.myAvaxID = null;
|
||||
floGlobals.myBscID = null;
|
||||
floGlobals.myMaticID = null;
|
||||
floGlobals.myArbID = null;
|
||||
floGlobals.myOpID = null;
|
||||
floGlobals.myHbarID = null;
|
||||
floGlobals.mySuiID = null;
|
||||
floGlobals.myAdaID = null;
|
||||
floGlobals.myTonID = null;
|
||||
floGlobals.myTronID = null;
|
||||
floGlobals.myDogeID = null;
|
||||
floGlobals.myLtcID = null;
|
||||
floGlobals.myBchID = null;
|
||||
floGlobals.myDotID = null;
|
||||
floGlobals.myAlgoID = null;
|
||||
floGlobals.myXlmID = null;
|
||||
floGlobals.mySolID = null;
|
||||
} else {
|
||||
floGlobals.myFloID = floCrypto.getFloID(floDapps.user.public);
|
||||
floGlobals.myBtcID = btcOperator.convert.legacy2bech(floGlobals.myFloID)
|
||||
floGlobals.myEthID = floEthereum.ethAddressFromCompressedPublicKey(floDapps.user.public)
|
||||
// AVAX C-Chain uses same address format as Ethereum
|
||||
floGlobals.myAvaxID = floGlobals.myEthID;
|
||||
// BSC (Binance Smart Chain) uses same address format as Ethereum
|
||||
floGlobals.myBscID = floGlobals.myEthID;
|
||||
// MATIC (Polygon) uses same address format as Ethereum
|
||||
floGlobals.myMaticID = floGlobals.myEthID;
|
||||
// Arbitrum uses same address format as Ethereum
|
||||
floGlobals.myArbID = floGlobals.myEthID;
|
||||
// Optimism uses same address format as Ethereum
|
||||
floGlobals.myOpID = floGlobals.myEthID;
|
||||
// HBAR (Hedera) uses same address format as Ethereum
|
||||
floGlobals.myHbarID = floGlobals.myEthID;
|
||||
|
||||
// Initialize private-key-dependent addresses to null (will be derived after messenger init)
|
||||
floGlobals.myXrpID = null;
|
||||
floGlobals.mySuiID = null;
|
||||
floGlobals.myAdaID = null;
|
||||
floGlobals.myTonID = null;
|
||||
floGlobals.myTronID = null;
|
||||
floGlobals.myDogeID = null;
|
||||
floGlobals.myLtcID = null;
|
||||
floGlobals.myBchID = null;
|
||||
floGlobals.myDotID = null;
|
||||
floGlobals.myAlgoID = null;
|
||||
floGlobals.myXlmID = null;
|
||||
floGlobals.mySolID = null;
|
||||
// Note: Cardano (ADA) address will be derived from private key later
|
||||
}
|
||||
document.querySelectorAll('.user-profile-id').forEach(el => el.textContent = floGlobals.myFloID)
|
||||
//load messages from IDB and render them
|
||||
console.log(`Loading Data! Please Wait...`)
|
||||
@ -230,7 +255,7 @@
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
notify(error, "error")
|
||||
notify(e, "error")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -2119,6 +2144,7 @@
|
||||
|
||||
const idList = allIds.filter(item => {
|
||||
if (!item.id) return false;
|
||||
if (activeChain === 'XRP') return item.label === 'XRP';
|
||||
if (item.label === 'FLO') return true; // Always include FLO
|
||||
if (item.label === activeChain) return true; // Include active chain
|
||||
// For EVM compatible chains which share the ETH ID:
|
||||
@ -2775,6 +2801,8 @@
|
||||
value.startsWith('suiprivkey1')
|
||||
) {
|
||||
isValid = true;
|
||||
} else if (value.startsWith('s') && value.length >= 29 && value.length <= 32) {
|
||||
isValid = true;
|
||||
} else if (value.startsWith('S') && value.length === 56) {
|
||||
isValid = true;
|
||||
} else {
|
||||
@ -2837,7 +2865,22 @@
|
||||
console.error("Failed to decode SUI key", e);
|
||||
}
|
||||
}
|
||||
else if (privateKey.startsWith('s')) activeChain = 'XRP';
|
||||
else if (privateKey.startsWith('s') && privateKey.length >= 29 && privateKey.length <= 32) {
|
||||
activeChain = 'XRP';
|
||||
// Convert XRP secret to workable FLO WIF using the private key bytes
|
||||
try {
|
||||
let wallet = xrpl.Wallet.fromSeed(privateKey);
|
||||
let privKeyHex = wallet.privateKey;
|
||||
// Remove ED prefix if present (Ed25519 keys)
|
||||
if (privKeyHex.startsWith('ED') || privKeyHex.startsWith('ed'))
|
||||
privKeyHex = privKeyHex.substring(2);
|
||||
let key = new Bitcoin.ECKey(privKeyHex);
|
||||
key.setCompressed(true);
|
||||
privateKey = key.getBitcoinWalletImportFormat();
|
||||
} catch (e) {
|
||||
console.error("Failed to decode XRP key", e);
|
||||
}
|
||||
}
|
||||
else if (privateKey.startsWith('Q')) activeChain = 'DOGE';
|
||||
else if (privateKey.startsWith('T') && privateKey.length === 51) activeChain = 'LTC';
|
||||
else if (privateKey.startsWith('K') || privateKey.startsWith('L') || privateKey.startsWith('5')) {
|
||||
@ -3327,8 +3370,19 @@
|
||||
}
|
||||
},
|
||||
profile() {
|
||||
let activeChain = localStorage.getItem(`${floGlobals.application}#activeChain`);
|
||||
return html`
|
||||
<div class="grid gap-1-5">
|
||||
${activeChain === 'XRP' ? html`
|
||||
<div class="grid gap-0-5">
|
||||
<h4>XRP-only login</h4>
|
||||
<p>You are logged in with an XRP private key. Only the XRP address is available.</p>
|
||||
</div>
|
||||
<div class="grid gap-0-5">
|
||||
<b>My XRP (Ripple) address</b>
|
||||
<sm-copy class="user-xrp-id" value=${floGlobals.myXrpID}></sm-copy>
|
||||
</div>
|
||||
` : html`
|
||||
<div class="grid gap-0-5">
|
||||
<h4>
|
||||
BTC integrated with FLO
|
||||
@ -3429,6 +3483,7 @@
|
||||
Unlock all addresses
|
||||
</button>
|
||||
` : ''}
|
||||
`}
|
||||
<button class="button button--danger justify-self-start" onclick="signOut()">Sign out</button>
|
||||
</div>
|
||||
<div class="grid gap-1">
|
||||
|
||||
@ -393,8 +393,21 @@
|
||||
return;
|
||||
var bytes;
|
||||
|
||||
// XRP Address (Base58, starts with 'r', 25-35 chars) - must be checked before FLO/BTC legacy
|
||||
if (address.length >= 25 && address.length <= 35 && address.startsWith('r')) {
|
||||
try {
|
||||
// XRP address - hash the raw address for unique proxy ID
|
||||
let addrBytes = [];
|
||||
for (let i = 0; i < address.length; i++) {
|
||||
addrBytes.push(address.charCodeAt(i));
|
||||
}
|
||||
bytes = ripemd160(Crypto.SHA256(addrBytes, { asBytes: true }));
|
||||
} catch (e) {
|
||||
bytes = undefined;
|
||||
}
|
||||
}
|
||||
// FLO/BTC legacy encoding (33-34 chars)
|
||||
if (address.length == 33 || address.length == 34) {
|
||||
else if (address.length == 33 || address.length == 34) {
|
||||
let decode = bitjs.Base58.decode(address);
|
||||
bytes = decode.slice(0, decode.length - 4);
|
||||
let checksum = decode.slice(decode.length - 4),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user