Updated on 2026-08-14
This commit is contained in:
parent
6e5b272987
commit
29e47d0782
3 changed files with 67 additions and 19 deletions
|
|
@ -137,7 +137,6 @@ dependencies {
|
|||
|
||||
//dependencies for XRP
|
||||
implementation files('libs/ripple-core-0.0.1.jar')
|
||||
implementation 'io.xpring:xpring4j:2.2.0'
|
||||
//4 dependencies for ripple-core TODO: move to module?
|
||||
implementation 'net.i2p.crypto:eddsa:0.3.0'
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.61'
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ import java.util.Arrays;
|
|||
|
||||
import io.reactivex.SingleObserver;
|
||||
import io.reactivex.observers.DisposableSingleObserver;
|
||||
import io.xpring.xrpl.ClassicAddress;
|
||||
import io.xpring.xrpl.Utils;
|
||||
|
||||
public class XrpEngine extends CoinEngine {
|
||||
|
||||
|
|
@ -142,12 +140,7 @@ public class XrpEngine extends CoinEngine {
|
|||
Addresses.decodeAccountID(address);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
// X-address
|
||||
ClassicAddress classicAddress = Utils.decodeXAddress(address);
|
||||
if (classicAddress == null) {
|
||||
return false;
|
||||
}
|
||||
return !classicAddress.isTest();
|
||||
return XrpXAddressService.Companion.validate(address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -367,10 +360,10 @@ public class XrpEngine extends CoinEngine {
|
|||
}
|
||||
|
||||
//X-address
|
||||
ClassicAddress classicAddress = Utils.decodeXAddress(destination);
|
||||
if (classicAddress != null) {
|
||||
destination = classicAddress.address();
|
||||
destinationTag = classicAddress.tag().get();
|
||||
XrpXAddressDecoded decodedXAddress = XrpXAddressService.Companion.decode(destination);
|
||||
if (decodedXAddress != null) {
|
||||
destination = decodedXAddress.getAddress();
|
||||
destinationTag = decodedXAddress.getDestinationTag();
|
||||
}
|
||||
|
||||
if (IncFee) {
|
||||
|
|
@ -564,7 +557,7 @@ public class XrpEngine extends CoinEngine {
|
|||
public void onSuccess(String method, RippleResponse rippleResponse) {
|
||||
Log.i(TAG, "onSuccess: " + method);
|
||||
switch (method) {
|
||||
case ServerApiRipple.RIPPLE_ACCOUNT_INFO: {
|
||||
case ServerApiRipple.RIPPLE_ACCOUNT_INFO: { //check if target account is created
|
||||
try {
|
||||
if (rippleResponse.getResult().getError_code().equals(19)) { // "Account not found"
|
||||
coinData.setTargetAccountCreated(false);
|
||||
|
|
@ -630,13 +623,12 @@ public class XrpEngine extends CoinEngine {
|
|||
|
||||
if (validateAddress(resolvedAddress)) {
|
||||
coinData.setResolvedPayIdAddress(resolvedAddress);
|
||||
//check if target account is created
|
||||
serverApiRipple.requestData(ServerApiRipple.RIPPLE_ACCOUNT_INFO, resolvedAddress, ""); //TODO: maybe just assume PayID account is created?
|
||||
} else {
|
||||
ctx.setError("Unknown address format in PayID response");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ctx.setError("FAIL payID Exception");
|
||||
ctx.setError("Unknown response format on PayID request");
|
||||
}
|
||||
if (serverApiRipple.isRequestsSequenceCompleted() && serverApiPayId.isRequestsSequenceCompleted()) {
|
||||
blockchainRequestsCallbacks.onComplete(!ctx.hasError());
|
||||
|
|
@ -648,15 +640,19 @@ public class XrpEngine extends CoinEngine {
|
|||
@Override
|
||||
public void onError(Throwable e) {
|
||||
Log.i(TAG, "onFail: " + "payID" + " " + e.getMessage());
|
||||
ctx.setError(e.getMessage());
|
||||
ctx.setError("PayID error:" + e.getMessage());
|
||||
blockchainRequestsCallbacks.onComplete(false);
|
||||
}
|
||||
};
|
||||
|
||||
serverApiPayId.getAddress(targetAddress, observer);
|
||||
} else {
|
||||
//check if target account is created
|
||||
serverApiRipple.requestData(ServerApiRipple.RIPPLE_ACCOUNT_INFO, targetAddress, "");
|
||||
XrpXAddressDecoded xAddressDecoded = XrpXAddressService.Companion.decode(targetAddress);
|
||||
if (xAddressDecoded == null) { // classic address
|
||||
serverApiRipple.requestData(ServerApiRipple.RIPPLE_ACCOUNT_INFO, targetAddress, "");
|
||||
} else { // X-address
|
||||
serverApiRipple.requestData(ServerApiRipple.RIPPLE_ACCOUNT_INFO, xAddressDecoded.getAddress(), "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
53
app/src/main/java/com/tangem/wallet/xrp/XrpTaggedAddress.kt
Normal file
53
app/src/main/java/com/tangem/wallet/xrp/XrpTaggedAddress.kt
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package com.tangem.wallet.xrp
|
||||
|
||||
import com.ripple.encodings.addresses.Addresses
|
||||
import com.ripple.encodings.base58.B58
|
||||
import org.kethereum.extensions.toBigInteger
|
||||
|
||||
class XrpXAddressService {
|
||||
companion object {
|
||||
private val xrpBase58 = B58("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz")
|
||||
private val xrpMainnetPrefix = byteArrayOf(0x05, 0x44)
|
||||
private val zeroTagBytes = ByteArray(4) { 0 }
|
||||
|
||||
fun validate(address: String): Boolean {
|
||||
return decode(address) != null
|
||||
}
|
||||
|
||||
fun decode(address: String): XrpXAddressDecoded? {
|
||||
try {
|
||||
val addressBytes = xrpBase58.decodeChecked(address)
|
||||
if (addressBytes.size != 31) return null
|
||||
|
||||
val prefix = addressBytes.slice(0..1).toByteArray()
|
||||
if (!prefix.contentEquals(xrpMainnetPrefix)) return null
|
||||
|
||||
val accountBytes = addressBytes.slice(2..21).toByteArray()
|
||||
val classicAddress = Addresses.encodeAccountID(accountBytes)
|
||||
|
||||
val flag = addressBytes[22]
|
||||
|
||||
val tagBytes = addressBytes.slice(23..26).toByteArray()
|
||||
val reservedTagBytes = addressBytes.slice(27..30).toByteArray()
|
||||
if (!reservedTagBytes.contentEquals(zeroTagBytes)) return null
|
||||
|
||||
var tag: Int? = null
|
||||
when (flag) {
|
||||
0.toByte() -> if (!tagBytes.contentEquals(zeroTagBytes)) return null
|
||||
1.toByte() -> {
|
||||
tag = tagBytes.reversedArray().toBigInteger().toInt()
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
return XrpXAddressDecoded(classicAddress, tag)
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class XrpXAddressDecoded(
|
||||
val address: String,
|
||||
val destinationTag: Int?
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue