From faf57c96fcd7879dc80974cdff167856989a10d9 Mon Sep 17 00:00:00 2001 From: m2049r Date: Mon, 15 Feb 2021 21:38:26 +0100 Subject: [PATCH] add more output currencies (#714) --- app/build.gradle | 4 +- .../com/m2049r/xmrwallet/BaseActivity.java | 2 +- .../com/m2049r/xmrwallet/ReceiveFragment.java | 3 +- .../com/m2049r/xmrwallet/ScannerFragment.java | 9 +- .../java/com/m2049r/xmrwallet/TxFragment.java | 2 +- .../com/m2049r/xmrwallet/WalletActivity.java | 2 +- .../com/m2049r/xmrwallet/WalletFragment.java | 3 +- .../m2049r/xmrwallet/data/BarcodeData.java | 237 +++++---------- .../com/m2049r/xmrwallet/data/Crypto.java | 89 ++++++ .../com/m2049r/xmrwallet/data/TxDataBtc.java | 18 ++ .../com/m2049r/xmrwallet/data/UserNotes.java | 12 +- .../send/SendAddressWizardFragment.java | 280 +++++++++++++----- .../send/SendAmountWizardFragment.java | 3 +- .../send/SendBtcAmountWizardFragment.java | 26 +- .../send/SendBtcConfirmWizardFragment.java | 23 +- .../send/SendBtcSuccessWizardFragment.java | 15 +- .../xmrwallet/fragment/send/SendFragment.java | 48 ++- .../layout/TransactionInfoAdapter.java | 16 +- .../shift/sideshift/api/CreateOrder.java | 2 + .../shift/sideshift/api/SideShiftApi.java | 2 - .../sideshift/network/CreateOrderImpl.java | 6 +- .../network/QueryOrderParametersImpl.java | 3 +- .../sideshift/network/RequestQuoteImpl.java | 5 +- .../com/m2049r/xmrwallet/util/Helper.java | 13 - .../xmrwallet/util/OpenAliasHelper.java | 6 +- .../m2049r/xmrwallet/util/ServiceHelper.java | 24 ++ .../util/validator/BitcoinAddressType.java | 51 ++++ .../BitcoinAddressValidator.java | 70 +++-- .../util/validator/EthAddressValidator.java | 64 ++++ .../xmrwallet/widget/ExchangeEditText.java | 18 +- .../widget/ExchangeOtherEditText.java | 24 +- .../m2049r/xmrwallet/widget/ExchangeView.java | 3 +- app/src/main/res/drawable/ic_monero.xml | 12 + app/src/main/res/drawable/ic_monero_bw.xml | 12 + .../main/res/drawable/ic_sideshift_circle.xml | 12 + .../main/res/drawable/ic_sideshift_white.xml | 84 +++--- app/src/main/res/drawable/ic_xmrto_32dp.png | Bin 1898 -> 0 bytes app/src/main/res/drawable/ic_xmrto_btc.xml | 14 + .../main/res/drawable/ic_xmrto_btc_off.xml | 14 + app/src/main/res/drawable/ic_xmrto_dash.xml | 15 + .../main/res/drawable/ic_xmrto_dash_off.xml | 15 + app/src/main/res/drawable/ic_xmrto_doge.xml | 14 + .../main/res/drawable/ic_xmrto_doge_off.xml | 14 + app/src/main/res/drawable/ic_xmrto_eth.xml | 38 +++ .../main/res/drawable/ic_xmrto_eth_off.xml | 38 +++ app/src/main/res/drawable/ic_xmrto_ltc.xml | 14 + .../main/res/drawable/ic_xmrto_ltc_off.xml | 14 + .../drawable/ic_xmrto_whitestroke_24px.png | Bin 1310 -> 0 bytes .../main/res/layout/fragment_send_address.xml | 113 ++++--- .../res/layout/fragment_send_btc_amount.xml | 8 +- .../res/layout/fragment_send_btc_confirm.xml | 5 +- .../res/layout/fragment_send_btc_success.xml | 30 +- .../main/res/layout/fragment_send_success.xml | 7 +- app/src/main/res/layout/fragment_tx_info.xml | 6 +- app/src/main/res/layout/item_transaction.xml | 2 +- app/src/main/res/values-cat/strings.xml | 48 +-- app/src/main/res/values-de/strings.xml | 49 +-- app/src/main/res/values-el/strings.xml | 48 +-- app/src/main/res/values-eo/strings.xml | 48 +-- app/src/main/res/values-es/strings.xml | 48 +-- app/src/main/res/values-et/strings.xml | 48 +-- app/src/main/res/values-fr/strings.xml | 48 +-- app/src/main/res/values-hu/strings.xml | 48 +-- app/src/main/res/values-it/strings.xml | 48 +-- app/src/main/res/values-ja/strings.xml | 48 +-- app/src/main/res/values-nb/strings.xml | 48 +-- app/src/main/res/values-nl/strings.xml | 48 +-- app/src/main/res/values-pt-rBR/strings.xml | 48 +-- app/src/main/res/values-pt/strings.xml | 48 +-- app/src/main/res/values-ro/strings.xml | 48 +-- app/src/main/res/values-ru/strings.xml | 48 +-- app/src/main/res/values-sk/strings.xml | 48 +-- app/src/main/res/values-sr/strings.xml | 48 +-- app/src/main/res/values-sv/strings.xml | 48 +-- app/src/main/res/values-uk/strings.xml | 48 +-- app/src/main/res/values-zh-rCN/strings.xml | 51 ++-- app/src/main/res/values-zh-rTW/strings.xml | 48 +-- app/src/main/res/values/strings.xml | 62 ++-- app/src/main/res/values/styles.xml | 5 + .../util/BitcoinAddressValidatorTest.java | 92 ------ .../xmrwallet/util/OpenAliasHelperTest.java | 2 +- .../BitcoinAddressValidatorTest.java | 139 +++++++++ .../validator/EthAddressValidatorTest.java | 46 +++ 83 files changed, 1866 insertions(+), 1104 deletions(-) create mode 100644 app/src/main/java/com/m2049r/xmrwallet/data/Crypto.java create mode 100644 app/src/main/java/com/m2049r/xmrwallet/util/ServiceHelper.java create mode 100644 app/src/main/java/com/m2049r/xmrwallet/util/validator/BitcoinAddressType.java rename app/src/main/java/com/m2049r/xmrwallet/util/{ => validator}/BitcoinAddressValidator.java (74%) create mode 100644 app/src/main/java/com/m2049r/xmrwallet/util/validator/EthAddressValidator.java create mode 100644 app/src/main/res/drawable/ic_monero.xml create mode 100644 app/src/main/res/drawable/ic_monero_bw.xml create mode 100644 app/src/main/res/drawable/ic_sideshift_circle.xml delete mode 100644 app/src/main/res/drawable/ic_xmrto_32dp.png create mode 100644 app/src/main/res/drawable/ic_xmrto_btc.xml create mode 100644 app/src/main/res/drawable/ic_xmrto_btc_off.xml create mode 100644 app/src/main/res/drawable/ic_xmrto_dash.xml create mode 100644 app/src/main/res/drawable/ic_xmrto_dash_off.xml create mode 100644 app/src/main/res/drawable/ic_xmrto_doge.xml create mode 100644 app/src/main/res/drawable/ic_xmrto_doge_off.xml create mode 100644 app/src/main/res/drawable/ic_xmrto_eth.xml create mode 100644 app/src/main/res/drawable/ic_xmrto_eth_off.xml create mode 100644 app/src/main/res/drawable/ic_xmrto_ltc.xml create mode 100644 app/src/main/res/drawable/ic_xmrto_ltc_off.xml delete mode 100644 app/src/main/res/drawable/ic_xmrto_whitestroke_24px.png delete mode 100644 app/src/test/java/com/m2049r/xmrwallet/util/BitcoinAddressValidatorTest.java create mode 100644 app/src/test/java/com/m2049r/xmrwallet/util/validator/BitcoinAddressValidatorTest.java create mode 100644 app/src/test/java/com/m2049r/xmrwallet/util/validator/EthAddressValidatorTest.java diff --git a/app/build.gradle b/app/build.gradle index c2bb0b4ef9..8e4a678f01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.m2049r.xmrwallet" minSdkVersion 21 targetSdkVersion 29 - versionCode 702 - versionName "1.17.2 'Druk'" + versionCode 705 + versionName "1.17.5.1 'Druk'" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { diff --git a/app/src/main/java/com/m2049r/xmrwallet/BaseActivity.java b/app/src/main/java/com/m2049r/xmrwallet/BaseActivity.java index 43185b24c2..d30f297825 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/BaseActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/BaseActivity.java @@ -213,7 +213,7 @@ private void processNfcIntent(Intent intent) { if (uri == null) { Toast.makeText(this, getString(R.string.nfc_tag_read_undef), Toast.LENGTH_LONG).show(); } else { - BarcodeData bc = BarcodeData.fromQrCode(uri.toString()); + BarcodeData bc = BarcodeData.fromString(uri.toString()); if (bc == null) Toast.makeText(this, getString(R.string.nfc_tag_read_undef), Toast.LENGTH_LONG).show(); else diff --git a/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java b/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java index ffc0c5b43a..2c0276a388 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java @@ -58,6 +58,7 @@ import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import com.m2049r.xmrwallet.BuildConfig; import com.m2049r.xmrwallet.data.BarcodeData; +import com.m2049r.xmrwallet.data.Crypto; import com.m2049r.xmrwallet.ledger.LedgerProgressDialog; import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.WalletManager; @@ -469,7 +470,7 @@ private void generateQr() { Timber.d("CLEARQR"); return; } - bcData = new BarcodeData(BarcodeData.Asset.XMR, address, notes, xmrAmount); + bcData = new BarcodeData(Crypto.XMR, address, notes, xmrAmount); int size = Math.max(ivQrCode.getWidth(), ivQrCode.getHeight()); Bitmap qr = generate(bcData.getUriString(), size, size); if (qr != null) { diff --git a/app/src/main/java/com/m2049r/xmrwallet/ScannerFragment.java b/app/src/main/java/com/m2049r/xmrwallet/ScannerFragment.java index 4f08cdd0af..32512fdfe6 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/ScannerFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/ScannerFragment.java @@ -73,14 +73,7 @@ public void handleResult(Result rawResult) { // * On older devices continuously stopping and resuming camera preview can result in freezing the app. // * I don't know why this is the case but I don't have the time to figure out. Handler handler = new Handler(); - handler.postDelayed(new - - Runnable() { - @Override - public void run() { - mScannerView.resumeCameraPreview(ScannerFragment.this); - } - }, 2000); + handler.postDelayed(() -> mScannerView.resumeCameraPreview(ScannerFragment.this), 2000); } @Override diff --git a/app/src/main/java/com/m2049r/xmrwallet/TxFragment.java b/app/src/main/java/com/m2049r/xmrwallet/TxFragment.java index ccf72c42cd..22e199b9dc 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/TxFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/TxFragment.java @@ -300,7 +300,7 @@ void showBtcInfo() { } tvTxXmrToKey.setText(key); tvDestinationBtc.setText(userNotes.xmrtoDestination); - tvTxAmountBtc.setText(userNotes.xmrtoAmount + " BTC"); + tvTxAmountBtc.setText(userNotes.xmrtoAmount + " "+ userNotes.xmrtoCurrency); switch (userNotes.xmrtoTag) { case "xmrto": tvXmrToSupport.setVisibility(View.GONE); diff --git a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java index 87de0d81af..10d6c1d2b8 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java @@ -921,7 +921,7 @@ public void onScan() { @Override public boolean onScanned(String qrCode) { // #gurke - BarcodeData bcData = BarcodeData.fromQrCode(qrCode); + BarcodeData bcData = BarcodeData.fromString(qrCode); if (bcData != null) { popFragmentStack(null); Timber.d("AAA"); diff --git a/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java b/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java index f441ac5225..1a1ac1032f 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java @@ -49,6 +49,7 @@ import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback; import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate; import com.m2049r.xmrwallet.util.Helper; +import com.m2049r.xmrwallet.util.ServiceHelper; import com.m2049r.xmrwallet.widget.Toolbar; import java.text.NumberFormat; @@ -242,7 +243,7 @@ void updateBalance() { String balanceCurrency = Helper.BASE_CRYPTO; double balanceRate = 1.0; - private final ExchangeApi exchangeApi = Helper.getExchangeApi(); + private final ExchangeApi exchangeApi = ServiceHelper.getExchangeApi(); void refreshBalance() { double unconfirmedXmr = Helper.getDecimalAmount(balance - unlockedBalance).doubleValue(); diff --git a/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java b/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java index 8d2b60f7a0..eb155f15b1 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java +++ b/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java @@ -18,69 +18,57 @@ import android.net.Uri; -import com.m2049r.xmrwallet.model.Wallet; -import com.m2049r.xmrwallet.util.BitcoinAddressValidator; import com.m2049r.xmrwallet.util.OpenAliasHelper; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import lombok.ToString; import timber.log.Timber; +@ToString public class BarcodeData { - - public static final String XMR_SCHEME = "monero:"; - public static final String XMR_PAYMENTID = "tx_payment_id"; - public static final String XMR_AMOUNT = "tx_amount"; - public static final String XMR_DESCRIPTION = "tx_description"; - - public static final String OA_XMR_ASSET = "xmr"; - public static final String OA_BTC_ASSET = "btc"; - - static final String BTC_SCHEME = "bitcoin"; - static final String BTC_DESCRIPTION = "message"; - static final String BTC_AMOUNT = "amount"; - - public enum Asset { - XMR, BTC - } - public enum Security { NORMAL, OA_NO_DNSSEC, OA_DNSSEC } - final public Asset asset; + final public Crypto asset; + final public List ambiguousAssets; final public String address; final public String addressName; final public String amount; final public String description; final public Security security; - public BarcodeData(Asset asset, String address) { - this(asset, address, null, null, null, Security.NORMAL); - } - - public BarcodeData(Asset asset, String address, String amount) { - this(asset, address, null, null, amount, Security.NORMAL); - } - - public BarcodeData(Asset asset, String address, String amount, String description, Security security) { - this(asset, address, null, description, amount, security); - } - - public BarcodeData(Asset asset, String address, String paymentId, String description, String amount) { - this(asset, address, null, description, amount, Security.NORMAL); + public BarcodeData(List assets, String address) { + if (assets.isEmpty()) + throw new IllegalArgumentException("no assets specified"); + this.addressName = null; + this.description = null; + this.amount = null; + this.security = Security.NORMAL; + this.address = address; + if (assets.size() == 1) { + this.asset = assets.get(0); + this.ambiguousAssets = null; + } else { + this.asset = null; + this.ambiguousAssets = assets; + } } - public BarcodeData(Asset asset, String address, String description, String amount) { + public BarcodeData(Crypto asset, String address, String description, String amount) { this(asset, address, null, description, amount, Security.NORMAL); } - public BarcodeData(Asset asset, String address, String addressName, String description, String amount, Security security) { + public BarcodeData(Crypto asset, String address, String addressName, String description, String amount, Security security) { + this.ambiguousAssets = null; this.asset = asset; this.address = address; this.addressName = addressName; @@ -94,133 +82,54 @@ public Uri getUri() { } public String getUriString() { - if (asset != Asset.XMR) throw new IllegalStateException("We can only do XMR stuff!"); + if (asset != Crypto.XMR) throw new IllegalStateException("We can only do XMR stuff!"); StringBuilder sb = new StringBuilder(); - sb.append(BarcodeData.XMR_SCHEME).append(address); + sb.append(Crypto.XMR.getUriScheme()).append(address); boolean first = true; if ((description != null) && !description.isEmpty()) { sb.append(first ? "?" : "&"); first = false; - sb.append(BarcodeData.XMR_DESCRIPTION).append('=').append(Uri.encode(description)); + sb.append(Crypto.XMR.getUriMessage()).append('=').append(Uri.encode(description)); } if ((amount != null) && !amount.isEmpty()) { sb.append(first ? "?" : "&"); - sb.append(BarcodeData.XMR_AMOUNT).append('=').append(amount); + sb.append(Crypto.XMR.getUriAmount()).append('=').append(amount); } return sb.toString(); } - static public BarcodeData fromQrCode(String qrCode) { - // check for monero uri - BarcodeData bcData = parseMoneroUri(qrCode); - // check for naked monero address / integrated address - if (bcData == null) { - bcData = parseMoneroNaked(qrCode); - } - // check for btc uri - if (bcData == null) { - bcData = parseBitcoinUri(qrCode); - } - // check for naked btc address - if (bcData == null) { - bcData = parseBitcoinNaked(qrCode); - } - // check for OpenAlias - if (bcData == null) { - bcData = parseOpenAlias(qrCode, false); - } - return bcData; - } - - /** - * Parse and decode a monero scheme string. It is here because it needs to validate the data. - * - * @param uri String containing a monero URL - * @return BarcodeData object or null if uri not valid - */ - - static public BarcodeData parseMoneroUri(String uri) { - Timber.d("parseMoneroUri=%s", uri); - - if (uri == null) return null; - - if (!uri.startsWith(XMR_SCHEME)) return null; - - String noScheme = uri.substring(XMR_SCHEME.length()); - Uri monero = Uri.parse(noScheme); - Map parms = new HashMap<>(); - String query = monero.getEncodedQuery(); - if (query != null) { - String[] args = query.split("&"); - for (String arg : args) { - String[] namevalue = arg.split("="); - if (namevalue.length == 0) { - continue; - } - parms.put(Uri.decode(namevalue[0]).toLowerCase(), - namevalue.length > 1 ? Uri.decode(namevalue[1]) : ""); - } - } - String address = monero.getPath(); - - String paymentId = parms.get(XMR_PAYMENTID); - // no support for payment ids! - if (paymentId != null) { - Timber.e("no support for payment ids!"); - return null; - } - - String description = parms.get(XMR_DESCRIPTION); - String amount = parms.get(XMR_AMOUNT); - if (amount != null) { - try { - Double.parseDouble(amount); - } catch (NumberFormatException ex) { - Timber.d(ex.getLocalizedMessage()); - return null; // we have an amount but its not a number! + static private BarcodeData parseNaked(String address) { + List possibleAssets = new ArrayList<>(); + for (Crypto crypto : Crypto.values()) { + if (crypto.validate(address)) { + possibleAssets.add(crypto); } } - - if ((address == null) || !Wallet.isAddressValid(address)) { - Timber.d("address invalid"); - return null; - } - return new BarcodeData(Asset.XMR, address, description, amount); - } - - static public BarcodeData parseMoneroNaked(String address) { - Timber.d("parseMoneroNaked=%s", address); - - if (address == null) return null; - - if (!Wallet.isAddressValid(address)) { - Timber.d("address invalid"); + if (possibleAssets.isEmpty()) return null; - } - - return new BarcodeData(Asset.XMR, address); + return new BarcodeData(possibleAssets, address); } - // bitcoin:mpQ84J43EURZHkCnXbyQ4PpNDLLBqdsMW2?amount=0.01 - // bitcoin:?r=https://bitpay.com/i/xxx - static public BarcodeData parseBitcoinUri(String uriString) { - Timber.d("parseBitcoinUri=%s", uriString); + static public BarcodeData parseUri(String uriString) { + Timber.d("parseBitUri=%s", uriString); - if (uriString == null) return null; URI uri; try { uri = new URI(uriString); } catch (URISyntaxException ex) { return null; } - if (!uri.isOpaque() || - !uri.getScheme().equals(BTC_SCHEME)) return null; + if (!uri.isOpaque()) return null; + final String scheme = uri.getScheme(); + Crypto crypto = Crypto.withScheme(scheme); + if (crypto == null) return null; String[] parts = uri.getRawSchemeSpecificPart().split("[?]"); if ((parts.length <= 0) || (parts.length > 2)) { Timber.d("invalid number of parts %d", parts.length); return null; } + Map parms = new HashMap<>(); if (parts.length == 2) { String[] args = parts[1].split("&"); @@ -233,17 +142,19 @@ static public BarcodeData parseBitcoinUri(String uriString) { namevalue.length > 1 ? Uri.decode(namevalue[1]) : ""); } } - String description = parms.get(BTC_DESCRIPTION); - String address = parts[0]; // no need to decode as there can bo no special characters + + String addressName = parms.get(crypto.getUriLabel()); + String description = parms.get(crypto.getUriMessage()); + String address = parts[0]; // no need to decode as there can be no special characters if (address.isEmpty()) { Timber.d("no address"); return null; } - if (!BitcoinAddressValidator.validate(address)) { - Timber.d("BTC address (%s) invalid", address); + if (!crypto.validate(address)) { + Timber.d("%s address (%s) invalid", crypto, address); return null; } - String amount = parms.get(BTC_AMOUNT); + String amount = parms.get(crypto.getUriAmount()); if ((amount != null) && (!amount.isEmpty())) { try { Double.parseDouble(amount); @@ -252,20 +163,21 @@ static public BarcodeData parseBitcoinUri(String uriString) { return null; // we have an amount but its not a number! } } - return new BarcodeData(BarcodeData.Asset.BTC, address, description, amount); + return new BarcodeData(crypto, address, addressName, description, amount, Security.NORMAL); } - static public BarcodeData parseBitcoinNaked(String address) { - Timber.d("parseBitcoinNaked=%s", address); - - if (address == null) return null; - if (!BitcoinAddressValidator.validate(address)) { - Timber.d("address invalid"); - return null; + static public BarcodeData fromString(String qrCode) { + BarcodeData bcData = parseUri(qrCode); + if (bcData == null) { + // maybe it's naked? + bcData = parseNaked(qrCode); } - - return new BarcodeData(BarcodeData.Asset.BTC, address); + if (bcData == null) { + // check for OpenAlias + bcData = parseOpenAlias(qrCode, false); + } + return bcData; } static public BarcodeData parseOpenAlias(String oaString, boolean dnssec) { @@ -281,29 +193,16 @@ static public BarcodeData parseOpenAlias(String oaString, boolean dnssec) { String address = oaAttrs.get(OpenAliasHelper.OA1_ADDRESS); if (address == null) return null; - Asset asset; - if (OA_XMR_ASSET.equals(oaAsset)) { - if (!Wallet.isAddressValid(address)) { - Timber.d("XMR address invalid"); - return null; - } - asset = Asset.XMR; - } else if (OA_BTC_ASSET.equals(oaAsset)) { - if (!BitcoinAddressValidator.validate(address)) { - Timber.d("BTC address invalid"); - return null; - } - asset = Asset.BTC; - } else { + Crypto crypto = Crypto.withSymbol(oaAsset); + if (crypto == null) { Timber.i("Unsupported OpenAlias asset %s", oaAsset); return null; } - - String paymentId = oaAttrs.get(OpenAliasHelper.OA1_PAYMENTID); - if (paymentId != null) { - Timber.e("paymentId not supported"); + if (!crypto.validate(address)) { + Timber.d("%s address invalid", crypto); return null; } + String description = oaAttrs.get(OpenAliasHelper.OA1_DESCRIPTION); if (description == null) { description = oaAttrs.get(OpenAliasHelper.OA1_NAME); @@ -322,6 +221,10 @@ static public BarcodeData parseOpenAlias(String oaString, boolean dnssec) { Security sec = dnssec ? BarcodeData.Security.OA_DNSSEC : BarcodeData.Security.OA_NO_DNSSEC; - return new BarcodeData(asset, address, addressName, description, amount, sec); + return new BarcodeData(crypto, address, addressName, description, amount, sec); + } + + public boolean isAmbiguous() { + return ambiguousAssets != null; } } \ No newline at end of file diff --git a/app/src/main/java/com/m2049r/xmrwallet/data/Crypto.java b/app/src/main/java/com/m2049r/xmrwallet/data/Crypto.java new file mode 100644 index 0000000000..e9e66f1dcd --- /dev/null +++ b/app/src/main/java/com/m2049r/xmrwallet/data/Crypto.java @@ -0,0 +1,89 @@ +package com.m2049r.xmrwallet.data; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.m2049r.xmrwallet.R; +import com.m2049r.xmrwallet.model.Wallet; +import com.m2049r.xmrwallet.util.validator.BitcoinAddressType; +import com.m2049r.xmrwallet.util.validator.BitcoinAddressValidator; +import com.m2049r.xmrwallet.util.validator.EthAddressValidator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum Crypto { + XMR("XMR", true, "monero:tx_amount:recipient_name:tx_description", R.id.ibXMR, R.drawable.ic_monero, R.drawable.ic_monero_bw, Wallet::isAddressValid), + BTC("BTC", true, "bitcoin:amount:label:message", R.id.ibBTC, R.drawable.ic_xmrto_btc, R.drawable.ic_xmrto_btc_off, address -> { + return BitcoinAddressValidator.validate(address, BitcoinAddressType.BTC); + }), + DASH("DASH", true, "dash:amount:label:message", R.id.ibDASH, R.drawable.ic_xmrto_dash, R.drawable.ic_xmrto_dash_off, address -> { + return BitcoinAddressValidator.validate(address, BitcoinAddressType.DASH); + }), + DOGE("DOGE", true, "dogecoin:amount:label:message", R.id.ibDOGE, R.drawable.ic_xmrto_doge, R.drawable.ic_xmrto_doge_off, address -> { + return BitcoinAddressValidator.validate(address, BitcoinAddressType.DOGE); + }), + ETH("ETH", false, "ethereum:amount:label:message", R.id.ibETH, R.drawable.ic_xmrto_eth, R.drawable.ic_xmrto_eth_off, EthAddressValidator::validate), + LTC("LTC", true, "litecoin:amount:label:message", R.id.ibLTC, R.drawable.ic_xmrto_ltc, R.drawable.ic_xmrto_ltc_off, address -> { + return BitcoinAddressValidator.validate(address, BitcoinAddressType.LTC); + }); + + @Getter + @NonNull + private final String symbol; + @Getter + private final boolean casefull; + @NonNull + private final String uriSpec; + @Getter + private final int buttonId; + @Getter + private final int iconEnabledId; + @Getter + private final int iconDisabledId; + @NonNull + private final Validator validator; + + @Nullable + public static Crypto withScheme(@NonNull String scheme) { + for (Crypto crypto : values()) { + if (crypto.getUriScheme().equals(scheme)) return crypto; + } + return null; + } + + @Nullable + public static Crypto withSymbol(@NonNull String symbol) { + final String upperSymbol = symbol.toUpperCase(); + for (Crypto crypto : values()) { + if (crypto.symbol.equals(upperSymbol)) return crypto; + } + return null; + } + + interface Validator { + boolean validate(String address); + } + + // TODO maybe cache these segments + String getUriScheme() { + return uriSpec.split(":")[0]; + } + + String getUriAmount() { + return uriSpec.split(":")[1]; + } + + String getUriLabel() { + return uriSpec.split(":")[2]; + } + + String getUriMessage() { + return uriSpec.split(":")[3]; + } + + boolean validate(String address) { + return validator.validate(address); + } +} diff --git a/app/src/main/java/com/m2049r/xmrwallet/data/TxDataBtc.java b/app/src/main/java/com/m2049r/xmrwallet/data/TxDataBtc.java index d95dbd23e3..55ec71a0cf 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/data/TxDataBtc.java +++ b/app/src/main/java/com/m2049r/xmrwallet/data/TxDataBtc.java @@ -24,6 +24,9 @@ import lombok.Setter; public class TxDataBtc extends TxData { + @Getter + @Setter + private String btcSymbol; // the actual non-XMR thing we're sending @Getter @Setter private String xmrtoOrderId; // shown in success screen @@ -45,6 +48,7 @@ public TxDataBtc(TxDataBtc txDataBtc) { @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); + out.writeString(btcSymbol); out.writeString(xmrtoOrderId); out.writeString(btcAddress); out.writeDouble(btcAmount); @@ -63,6 +67,7 @@ public TxDataBtc[] newArray(int size) { protected TxDataBtc(Parcel in) { super(in); + btcSymbol = in.readString(); xmrtoOrderId = in.readString(); btcAddress = in.readString(); btcAmount = in.readDouble(); @@ -74,10 +79,23 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("xmrtoOrderId:"); sb.append(xmrtoOrderId); + sb.append(",btcSymbol:"); + sb.append(btcSymbol); sb.append(",btcAddress:"); sb.append(btcAddress); sb.append(",btcAmount:"); sb.append(btcAmount); return sb.toString(); } + + public boolean validateAddress(@NonNull String address) { + if ((btcSymbol == null) || (btcAddress == null)) return false; + final Crypto crypto = Crypto.withSymbol(btcSymbol); + if (crypto == null) return false; + if (crypto.isCasefull()) { // compare as-is + return address.equals(btcAddress); + } else { // normalize & compare (e.g. ETH with and without checksum capitals + return address.toLowerCase().equals(btcAddress.toLowerCase()); + } + } } diff --git a/app/src/main/java/com/m2049r/xmrwallet/data/UserNotes.java b/app/src/main/java/com/m2049r/xmrwallet/data/UserNotes.java index 0e831059ce..f5eb14b503 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/data/UserNotes.java +++ b/app/src/main/java/com/m2049r/xmrwallet/data/UserNotes.java @@ -28,6 +28,7 @@ public class UserNotes { public String xmrtoTag = null; public String xmrtoKey = null; public String xmrtoAmount = null; // could be a double - but we are not doing any calculations + public String xmrtoCurrency = null; public String xmrtoDestination = null; public UserNotes(final String txNotes) { @@ -35,14 +36,15 @@ public UserNotes(final String txNotes) { return; } this.txNotes = txNotes; - Pattern p = Pattern.compile("^\\{([a-z]+)-(\\w{6,}),([0-9.]*)BTC,(\\w*)\\} ?(.*)"); + Pattern p = Pattern.compile("^\\{([a-z]+)-(\\w{6,}),([0-9.]*)([A-Z]+),(\\w*)\\} ?(.*)"); Matcher m = p.matcher(txNotes); if (m.find()) { xmrtoTag = m.group(1); xmrtoKey = m.group(2); xmrtoAmount = m.group(3); - xmrtoDestination = m.group(4); - note = m.group(5); + xmrtoCurrency = m.group(4); + xmrtoDestination = m.group(5); + note = m.group(6); } else { note = txNotes; } @@ -62,6 +64,7 @@ public void setXmrtoOrder(CreateOrder order) { xmrtoTag = order.TAG; xmrtoKey = order.getOrderId(); xmrtoAmount = Helper.getDisplayAmount(order.getBtcAmount()); + xmrtoCurrency = order.getBtcCurrency(); xmrtoDestination = order.getBtcAddress(); } else { xmrtoTag = null; @@ -83,7 +86,8 @@ private String buildTxNote() { sb.append(xmrtoKey); sb.append(","); sb.append(xmrtoAmount); - sb.append("BTC,"); + sb.append(xmrtoCurrency); + sb.append(","); sb.append(xmrtoDestination); sb.append("}"); if ((note != null) && (!note.isEmpty())) diff --git a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java index 2ad428e8ee..5114b41708 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java @@ -39,16 +39,23 @@ import com.google.android.material.textfield.TextInputLayout; import com.m2049r.xmrwallet.R; import com.m2049r.xmrwallet.data.BarcodeData; +import com.m2049r.xmrwallet.data.Crypto; import com.m2049r.xmrwallet.data.TxData; import com.m2049r.xmrwallet.data.TxDataBtc; import com.m2049r.xmrwallet.data.UserNotes; import com.m2049r.xmrwallet.model.PendingTransaction; import com.m2049r.xmrwallet.model.Wallet; -import com.m2049r.xmrwallet.util.BitcoinAddressValidator; import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.OpenAliasHelper; +import com.m2049r.xmrwallet.util.ServiceHelper; +import com.m2049r.xmrwallet.util.validator.BitcoinAddressType; +import com.m2049r.xmrwallet.util.validator.BitcoinAddressValidator; +import com.m2049r.xmrwallet.util.validator.EthAddressValidator; +import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import timber.log.Timber; @@ -64,9 +71,8 @@ public static SendAddressWizardFragment newInstance(Listener listener) { Listener sendListener; - public SendAddressWizardFragment setSendListener(Listener listener) { + public void setSendListener(Listener listener) { this.sendListener = listener; - return this; } public interface Listener { @@ -84,11 +90,10 @@ public interface Listener { private EditText etDummy; private TextInputLayout etAddress; private TextInputLayout etNotes; - private View cvScan; - private View tvPaymentIdIntegrated; private TextView tvXmrTo; - private View llXmrTo; - private ImageButton bPasteAddress; + private Map ibCrypto; + final private Set possibleCryptos = new HashSet<>(); + private Crypto selectedCrypto = null; private boolean resolvingOA = false; @@ -98,6 +103,13 @@ public interface OnScanListener { void onScan(); } + private Crypto getCryptoForButton(ImageButton button) { + for (Map.Entry entry : ibCrypto.entrySet()) { + if (entry.getValue() == button) return entry.getKey(); + } + return null; + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -105,10 +117,31 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, View view = inflater.inflate(R.layout.fragment_send_address, container, false); - tvPaymentIdIntegrated = view.findViewById(R.id.tvPaymentIdIntegrated); - llXmrTo = view.findViewById(R.id.llXmrTo); tvXmrTo = view.findViewById(R.id.tvXmrTo); - tvXmrTo.setText(Html.fromHtml(getString(R.string.info_xmrto))); + + ibCrypto = new HashMap<>(); + for (Crypto crypto : Crypto.values()) { + final ImageButton button = view.findViewById(crypto.getButtonId()); + ibCrypto.put(crypto, button); + button.setOnClickListener(v -> { + if (possibleCryptos.contains(crypto)) { + selectedCrypto = crypto; + updateCryptoButtons(false); + } else { + // show help what to do: + if (button.getId() != R.id.ibXMR) { + final String name = getResources().getStringArray(R.array.cryptos)[crypto.ordinal()]; + final String symbol = getCryptoForButton(button).getSymbol(); + tvXmrTo.setText(Html.fromHtml(getString(R.string.info_xmrto_help, name, symbol))); + tvXmrTo.setVisibility(View.VISIBLE); + } else { + tvXmrTo.setText(Html.fromHtml(getString(R.string.info_xmrto_help_xmr))); + tvXmrTo.setVisibility(View.VISIBLE); + } + } + }); + } + updateCryptoButtons(true); etAddress = view.findViewById(R.id.etAddress); etAddress.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); @@ -118,16 +151,13 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { return ((event != null) && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)); } }); - etAddress.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (!hasFocus) { - String enteredAddress = etAddress.getEditText().getText().toString().trim(); - String dnsOA = dnsFromOpenAlias(enteredAddress); - Timber.d("OpenAlias is %s", dnsOA); - if (dnsOA != null) { - processOpenAlias(dnsOA); - } + etAddress.getEditText().setOnFocusChangeListener((v, hasFocus) -> { + if (!hasFocus) { + String enteredAddress = etAddress.getEditText().getText().toString().trim(); + String dnsOA = dnsFromOpenAlias(enteredAddress); + Timber.d("OpenAlias is %s", dnsOA); + if (dnsOA != null) { + processOpenAlias(dnsOA); } } }); @@ -136,21 +166,47 @@ public void onFocusChange(View v, boolean hasFocus) { public void afterTextChanged(Editable editable) { Timber.d("AFTER: %s", editable.toString()); etAddress.setError(null); - if (isIntegratedAddress()) { + possibleCryptos.clear(); + selectedCrypto = null; + final String address = etAddress.getEditText().getText().toString(); + if (isIntegratedAddress(address)) { Timber.d("isIntegratedAddress"); + possibleCryptos.add(Crypto.XMR); + selectedCrypto = Crypto.XMR; etAddress.setError(getString(R.string.info_paymentid_integrated)); - tvPaymentIdIntegrated.setVisibility(View.VISIBLE); - llXmrTo.setVisibility(View.INVISIBLE); sendListener.setMode(SendFragment.Mode.XMR); - } else if (isBitcoinAddress()) { + } else if (isStandardAddress(address)) { + Timber.d("isStandardAddress"); + possibleCryptos.add(Crypto.XMR); + selectedCrypto = Crypto.XMR; + sendListener.setMode(SendFragment.Mode.XMR); + } + if ((selectedCrypto == null) && isEthAddress(address)) { + Timber.d("isEthAddress"); + possibleCryptos.add(Crypto.ETH); + selectedCrypto = Crypto.ETH; + tvXmrTo.setVisibility(View.VISIBLE); + sendListener.setMode(SendFragment.Mode.BTC); + } + if (possibleCryptos.isEmpty()) { Timber.d("isBitcoinAddress"); - setBtcMode(); - } else { - Timber.d("isStandardAddress or other"); - tvPaymentIdIntegrated.setVisibility(View.INVISIBLE); - llXmrTo.setVisibility(View.INVISIBLE); + for (BitcoinAddressType type : BitcoinAddressType.values()) { + if (BitcoinAddressValidator.validate(address, type)) { + possibleCryptos.add(Crypto.valueOf(type.name())); + } + } + if (!possibleCryptos.isEmpty()) // found something in need of shifting! + sendListener.setMode(SendFragment.Mode.BTC); + if (possibleCryptos.size() == 1) { + selectedCrypto = (Crypto) possibleCryptos.toArray()[0]; + } + } + if (possibleCryptos.isEmpty()) { + Timber.d("other"); + tvXmrTo.setVisibility(View.INVISIBLE); sendListener.setMode(SendFragment.Mode.XMR); } + updateCryptoButtons(address.isEmpty()); } @Override @@ -162,45 +218,38 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { } }); - bPasteAddress = view.findViewById(R.id.bPasteAddress); - bPasteAddress.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - final String clip = Helper.getClipBoardText(getActivity()); - if (clip == null) return; - // clean it up - final String address = clip.replaceAll("[^0-9A-Z-a-z]", ""); - if (Wallet.isAddressValid(address) || BitcoinAddressValidator.validate(address)) { - final EditText et = etAddress.getEditText(); - et.setText(address); - et.setSelection(et.getText().length()); - etAddress.requestFocus(); - } else { - Toast.makeText(getActivity(), getString(R.string.send_address_invalid), Toast.LENGTH_SHORT).show(); - } + final ImageButton bPasteAddress = view.findViewById(R.id.bPasteAddress); + bPasteAddress.setOnClickListener(v -> { + final String clip = Helper.getClipBoardText(getActivity()); + if (clip == null) return; + // clean it up + final String address = clip.replaceAll("( +)|(\\r?\\n?)", ""); + BarcodeData bc = BarcodeData.fromString(address); + if (bc != null) { + processScannedData(bc); + final EditText et = etAddress.getEditText(); + et.setSelection(et.getText().length()); + etAddress.requestFocus(); + } else { + Toast.makeText(getActivity(), getString(R.string.send_address_invalid), Toast.LENGTH_SHORT).show(); } }); etNotes = view.findViewById(R.id.etNotes); etNotes.getEditText().setRawInputType(InputType.TYPE_CLASS_TEXT); - etNotes.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() { - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) - || (actionId == EditorInfo.IME_ACTION_DONE)) { - etDummy.requestFocus(); - return true; - } - return false; - } - }); + etNotes.getEditText(). - cvScan = view.findViewById(R.id.bScan); - cvScan.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - onScanListener.onScan(); - } - }); + setOnEditorActionListener((v, actionId, event) -> { + if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) + || (actionId == EditorInfo.IME_ACTION_DONE)) { + etDummy.requestFocus(); + return true; + } + return false; + }); + + final View cvScan = view.findViewById(R.id.bScan); + cvScan.setOnClickListener(v -> onScanListener.onScan()); etDummy = view.findViewById(R.id.etDummy); etDummy.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); @@ -214,11 +263,49 @@ public void onClick(View v) { return view; } - private void setBtcMode() { - Timber.d("setBtcMode"); - tvPaymentIdIntegrated.setVisibility(View.INVISIBLE); - llXmrTo.setVisibility(View.VISIBLE); - sendListener.setMode(SendFragment.Mode.BTC); + private void selectedCrypto(Crypto crypto) { + final ImageButton button = ibCrypto.get(crypto); + button.setImageResource(crypto.getIconEnabledId()); + button.setImageAlpha(255); + button.setEnabled(true); + } + + private void possibleCrypto(Crypto crypto) { + final ImageButton button = ibCrypto.get(crypto); + button.setImageResource(crypto.getIconDisabledId()); + button.setImageAlpha(255); + button.setEnabled(true); + } + + private void impossibleCrypto(Crypto crypto) { + final ImageButton button = ibCrypto.get(crypto); + button.setImageResource(crypto.getIconDisabledId()); + button.setImageAlpha(128); + button.setEnabled(true); + } + + private void updateCryptoButtons(boolean noAddress) { + for (Crypto crypto : Crypto.values()) { + if (crypto == selectedCrypto) { + selectedCrypto(crypto); + } else if (possibleCryptos.contains(crypto)) { + possibleCrypto(crypto); + } else { + impossibleCrypto(crypto); + } + } + if ((selectedCrypto != null) && (selectedCrypto != Crypto.XMR)) { + tvXmrTo.setText(Html.fromHtml(getString(R.string.info_xmrto, selectedCrypto.getSymbol()))); + tvXmrTo.setVisibility(View.VISIBLE); + } else if ((selectedCrypto == null) && (possibleCryptos.size() > 1)) { + tvXmrTo.setText(Html.fromHtml(getString(R.string.info_xmrto_ambiguous))); + tvXmrTo.setVisibility(View.VISIBLE); + } else { + tvXmrTo.setVisibility(View.INVISIBLE); + } + if (noAddress) { + selectedCrypto(Crypto.XMR); + } } private void processOpenAlias(String dnsOA) { @@ -229,10 +316,10 @@ private void processOpenAlias(String dnsOA) { etAddress.setError(getString(R.string.send_address_resolve_openalias)); OpenAliasHelper.resolve(dnsOA, new OpenAliasHelper.OnResolvedListener() { @Override - public void onResolved(Map dataMap) { + public void onResolved(Map dataMap) { resolvingOA = false; - BarcodeData barcodeData = dataMap.get(BarcodeData.Asset.XMR); - if (barcodeData == null) barcodeData = dataMap.get(BarcodeData.Asset.BTC); + BarcodeData barcodeData = dataMap.get(Crypto.XMR); + if (barcodeData == null) barcodeData = dataMap.get(Crypto.BTC); if (barcodeData != null) { Timber.d("Security=%s, %s", barcodeData.security.toString(), barcodeData.address); processScannedData(barcodeData); @@ -253,9 +340,7 @@ public void onFailure() { } private boolean checkAddressNoError() { - String address = etAddress.getEditText().getText().toString(); - return Wallet.isAddressValid(address) - || BitcoinAddressValidator.validate(address); + return selectedCrypto != null; } private boolean checkAddress() { @@ -268,19 +353,37 @@ private boolean checkAddress() { return ok; } - private boolean isIntegratedAddress() { - String address = etAddress.getEditText().getText().toString(); + private boolean isStandardAddress(String address) { + return Wallet.isAddressValid(address); + } + + private boolean isIntegratedAddress(String address) { return (address.length() == INTEGRATED_ADDRESS_LENGTH) && Wallet.isAddressValid(address); } - private boolean isBitcoinAddress() { - final String address = etAddress.getEditText().getText().toString(); - return BitcoinAddressValidator.validate(address); + private boolean isBitcoinishAddress(String address) { + return BitcoinAddressValidator.validate(address, BitcoinAddressType.BTC) + || + BitcoinAddressValidator.validate(address, BitcoinAddressType.LTC) + || + BitcoinAddressValidator.validate(address, BitcoinAddressType.DASH); + } + + private boolean isEthAddress(String address) { + return EthAddressValidator.validate(address); } private void shakeAddress() { - etAddress.startAnimation(Helper.getShakeAnimation(getContext())); + if (possibleCryptos.size() > 1) { // address ambiguous + for (Crypto crypto : Crypto.values()) { + if (possibleCryptos.contains(crypto)) { + ibCrypto.get(crypto).startAnimation(Helper.getShakeAnimation(getContext())); + } + } + } else { + etAddress.startAnimation(Helper.getShakeAnimation(getContext())); + } } @Override @@ -300,9 +403,12 @@ public boolean onValidateFields() { TxData txData = sendListener.getTxData(); if (txData instanceof TxDataBtc) { ((TxDataBtc) txData).setBtcAddress(etAddress.getEditText().getText().toString()); + ((TxDataBtc) txData).setBtcSymbol(selectedCrypto.getSymbol()); txData.setDestinationAddress(null); + ServiceHelper.ASSET = selectedCrypto.getSymbol().toLowerCase(); } else { txData.setDestinationAddress(etAddress.getEditText().getText().toString()); + ServiceHelper.ASSET = null; } txData.setUserNotes(new UserNotes(etNotes.getEditText().getText().toString())); txData.setPriority(PendingTransaction.Priority.Priority_Default); @@ -344,6 +450,15 @@ public void processScannedData() { if (barcodeData.address != null) { etAddress.getEditText().setText(barcodeData.address); + possibleCryptos.clear(); + selectedCrypto = null; + if (barcodeData.isAmbiguous()) { + possibleCryptos.addAll(barcodeData.ambiguousAssets); + } else { + possibleCryptos.add(barcodeData.asset); + selectedCrypto = barcodeData.asset; + } + updateCryptoButtons(false); if (checkAddress()) { if (barcodeData.security == BarcodeData.Security.OA_NO_DNSSEC) etAddress.setError(getString(R.string.send_address_no_dnssec)); @@ -355,7 +470,12 @@ else if (barcodeData.security == BarcodeData.Security.OA_DNSSEC) etAddress.setError(null); } - String scannedNotes = barcodeData.description; + String scannedNotes = barcodeData.addressName; + if (scannedNotes == null) { + scannedNotes = barcodeData.description; + } else if (barcodeData.description != null) { + scannedNotes = scannedNotes + ": " + barcodeData.description; + } if (scannedNotes != null) { etNotes.getEditText().setText(scannedNotes); } else { diff --git a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAmountWizardFragment.java b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAmountWizardFragment.java index a061df490f..3e66a87617 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAmountWizardFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAmountWizardFragment.java @@ -42,9 +42,8 @@ public static SendAmountWizardFragment newInstance(Listener listener) { Listener sendListener; - public SendAmountWizardFragment setSendListener(Listener listener) { + public void setSendListener(Listener listener) { this.sendListener = listener; - return this; } interface Listener { diff --git a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcAmountWizardFragment.java b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcAmountWizardFragment.java index b819d5cd67..f4b4ae0b2b 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcAmountWizardFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcAmountWizardFragment.java @@ -28,16 +28,16 @@ import com.m2049r.xmrwallet.data.BarcodeData; import com.m2049r.xmrwallet.data.TxDataBtc; import com.m2049r.xmrwallet.model.Wallet; -import com.m2049r.xmrwallet.util.Helper; -import com.m2049r.xmrwallet.util.OkHttpHelper; -import com.m2049r.xmrwallet.widget.ExchangeOtherEditText; -import com.m2049r.xmrwallet.widget.SendProgressView; +import com.m2049r.xmrwallet.service.shift.ShiftCallback; import com.m2049r.xmrwallet.service.shift.ShiftError; import com.m2049r.xmrwallet.service.shift.ShiftException; import com.m2049r.xmrwallet.service.shift.sideshift.api.QueryOrderParameters; import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi; -import com.m2049r.xmrwallet.service.shift.ShiftCallback; import com.m2049r.xmrwallet.service.shift.sideshift.network.SideShiftApiImpl; +import com.m2049r.xmrwallet.util.OkHttpHelper; +import com.m2049r.xmrwallet.util.ServiceHelper; +import com.m2049r.xmrwallet.widget.ExchangeOtherEditText; +import com.m2049r.xmrwallet.widget.SendProgressView; import java.text.NumberFormat; import java.util.Locale; @@ -85,6 +85,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, etAmount = view.findViewById(R.id.etAmount); etAmount.requestFocus(); + return view; } @@ -130,20 +131,26 @@ public void onPauseFragment() { public void onResumeFragment() { super.onResumeFragment(); Timber.d("onResumeFragment()"); + final String btcSymbol = ((TxDataBtc) sendListener.getTxData()).getBtcSymbol(); + if (!btcSymbol.toLowerCase().equals(ServiceHelper.ASSET)) + throw new IllegalStateException("Asset Symbol is wrong!"); final long funds = getTotalFunds(); if (!sendListener.getActivityCallback().isStreetMode()) { tvFunds.setText(getString(R.string.send_available, Wallet.getDisplayAmount(funds))); + //TODO } else { tvFunds.setText(getString(R.string.send_available, getString(R.string.unknown_amount))); } + etAmount.setAmount(""); final BarcodeData data = sendListener.popBarcodeData(); if (data != null) { if (data.amount != null) { etAmount.setAmount(data.amount); } } + etAmount.setBaseCurrency(btcSymbol); callXmrTo(); } @@ -166,7 +173,9 @@ private void processOrderParms(final QueryOrderParameters orderParameters) { String min = df.format(minBtc); String max = df.format(maxBtc); String rate = df.format(price); - Spanned xmrParmText = Html.fromHtml(getString(R.string.info_send_xmrto_parms, min, max, rate)); + final TxDataBtc txDataBtc = (TxDataBtc) sendListener.getTxData(); + Spanned xmrParmText = Html.fromHtml(getString(R.string.info_send_xmrto_parms, + min, max, rate, txDataBtc.getBtcSymbol())); tvXmrToParms.setText(xmrParmText); final long funds = getTotalFunds(); @@ -183,7 +192,8 @@ private void processOrderParms(final QueryOrderParameters orderParameters) { } tvFunds.setText(getString(R.string.send_available_btc, availXmrString, - availBtcString)); + availBtcString, + ((TxDataBtc) sendListener.getTxData()).getBtcSymbol())); llXmrToParms.setVisibility(View.VISIBLE); evParams.hideProgress(); }); @@ -246,7 +256,7 @@ private SideShiftApi getXmrToApi() { synchronized (this) { if (xmrToApi == null) { xmrToApi = new SideShiftApiImpl(OkHttpHelper.getOkHttpClient(), - Helper.getXmrToBaseUrl()); + ServiceHelper.getXmrToBaseUrl()); } } } diff --git a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcConfirmWizardFragment.java b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcConfirmWizardFragment.java index 27ff90dbe4..a37ece8922 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcConfirmWizardFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcConfirmWizardFragment.java @@ -29,16 +29,17 @@ import com.m2049r.xmrwallet.data.TxDataBtc; import com.m2049r.xmrwallet.model.PendingTransaction; import com.m2049r.xmrwallet.model.Wallet; -import com.m2049r.xmrwallet.util.Helper; -import com.m2049r.xmrwallet.util.OkHttpHelper; -import com.m2049r.xmrwallet.widget.SendProgressView; +import com.m2049r.xmrwallet.service.shift.ShiftCallback; import com.m2049r.xmrwallet.service.shift.ShiftError; import com.m2049r.xmrwallet.service.shift.ShiftException; import com.m2049r.xmrwallet.service.shift.sideshift.api.CreateOrder; import com.m2049r.xmrwallet.service.shift.sideshift.api.RequestQuote; import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi; -import com.m2049r.xmrwallet.service.shift.ShiftCallback; import com.m2049r.xmrwallet.service.shift.sideshift.network.SideShiftApiImpl; +import com.m2049r.xmrwallet.util.Helper; +import com.m2049r.xmrwallet.util.OkHttpHelper; +import com.m2049r.xmrwallet.util.ServiceHelper; +import com.m2049r.xmrwallet.widget.SendProgressView; import java.text.NumberFormat; import java.util.Locale; @@ -67,6 +68,7 @@ public void setSendListener(SendConfirmWizardFragment.Listener listener) { private TextView tvTxBtcAmount; private TextView tvTxBtcRate; private TextView tvTxBtcAddress; + private TextView tvTxBtcAddressLabel; private TextView tvTxXmrToKey; private TextView tvTxFee; private TextView tvTxTotal; @@ -84,6 +86,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, R.layout.fragment_send_btc_confirm, container, false); tvTxBtcAddress = view.findViewById(R.id.tvTxBtcAddress); + tvTxBtcAddressLabel = view.findViewById(R.id.tvTxBtcAddressLabel); tvTxBtcAmount = view.findViewById(R.id.tvTxBtcAmount); tvTxBtcRate = view.findViewById(R.id.tvTxBtcRate); tvTxXmrToKey = view.findViewById(R.id.tvTxXmrToKey); @@ -259,6 +262,8 @@ public void onResumeFragment() { if (sendListener.getMode() != SendFragment.Mode.BTC) { throw new IllegalStateException("Mode is not BTC!"); } + if (!((TxDataBtc) sendListener.getTxData()).getBtcSymbol().toLowerCase().equals(ServiceHelper.ASSET)) + throw new IllegalStateException("Asset Symbol is wrong!"); Helper.hideKeyboard(getActivity()); llStageA.setVisibility(View.INVISIBLE); evStageA.hideProgress(); @@ -392,9 +397,10 @@ private void processStageA(final RequestQuote requestQuote) { df.setMaximumFractionDigits(12); final String btcAmount = df.format(xmrtoQuote.getBtcAmount()); final String xmrAmountTotal = df.format(xmrtoQuote.getXmrAmount()); - tvTxBtcAmount.setText(getString(R.string.text_send_btc_amount, btcAmount, xmrAmountTotal)); + tvTxBtcAmount.setText(getString(R.string.text_send_btc_amount, + btcAmount, xmrAmountTotal, txDataBtc.getBtcSymbol())); final String xmrPriceBtc = df.format(xmrtoQuote.getPrice()); - tvTxBtcRate.setText(getString(R.string.text_send_btc_rate, xmrPriceBtc)); + tvTxBtcRate.setText(getString(R.string.text_send_btc_rate, xmrPriceBtc, txDataBtc.getBtcSymbol())); hideProgress(); }); stageB(requestQuote.getId()); @@ -477,13 +483,14 @@ private void processStageB(final CreateOrder order) { TxDataBtc txDataBtc = (TxDataBtc) sendListener.getTxData(); // verify amount & destination if ((order.getBtcAmount() != txDataBtc.getBtcAmount()) - || (!order.getBtcAddress().equals(txDataBtc.getBtcAddress()))) { + || (!txDataBtc.validateAddress(order.getBtcAddress()))) { throw new IllegalStateException("Order does not fulfill quote!"); // something is terribly wrong - die } xmrtoOrder = order; getView().post(() -> { tvTxXmrToKey.setText(order.getOrderId()); tvTxBtcAddress.setText(order.getBtcAddress()); + tvTxBtcAddressLabel.setText(getString(R.string.label_send_btc_address, txDataBtc.getBtcSymbol())); hideProgress(); Timber.d("Expires @ %s", order.getExpiresAt().toString()); final int timeout = (int) (order.getExpiresAt().getTime() - order.getCreatedAt().getTime()) / 1000 - 60; // -1 minute buffer @@ -561,7 +568,7 @@ private SideShiftApi getXmrToApi() { synchronized (this) { if (xmrToApi == null) { xmrToApi = new SideShiftApiImpl(OkHttpHelper.getOkHttpClient(), - Helper.getXmrToBaseUrl()); + ServiceHelper.getXmrToBaseUrl()); } } } diff --git a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcSuccessWizardFragment.java b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcSuccessWizardFragment.java index d2a6462a33..4156ee56e1 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcSuccessWizardFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendBtcSuccessWizardFragment.java @@ -30,6 +30,7 @@ import android.widget.Toast; import com.m2049r.xmrwallet.R; +import com.m2049r.xmrwallet.data.Crypto; import com.m2049r.xmrwallet.data.PendingTx; import com.m2049r.xmrwallet.data.TxDataBtc; import com.m2049r.xmrwallet.service.shift.ShiftCallback; @@ -39,6 +40,7 @@ import com.m2049r.xmrwallet.service.shift.sideshift.network.SideShiftApiImpl; import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.OkHttpHelper; +import com.m2049r.xmrwallet.util.ServiceHelper; import java.text.NumberFormat; import java.util.Locale; @@ -62,10 +64,10 @@ public void setSendListener(SendSuccessWizardFragment.Listener listener) { ImageButton bCopyTxId; private TextView tvTxId; private TextView tvTxAddress; - private TextView tvTxPaymentId; private TextView tvTxAmount; private TextView tvTxFee; private TextView tvXmrToAmount; + private ImageView ivXmrToIcon; private TextView tvXmrToStatus; private ImageView ivXmrToStatus; private ImageView ivXmrToStatusBig; @@ -90,13 +92,13 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, }); tvXmrToAmount = view.findViewById(R.id.tvXmrToAmount); + ivXmrToIcon = view.findViewById(R.id.ivXmrToIcon); tvXmrToStatus = view.findViewById(R.id.tvXmrToStatus); ivXmrToStatus = view.findViewById(R.id.ivXmrToStatus); ivXmrToStatusBig = view.findViewById(R.id.ivXmrToStatusBig); tvTxId = view.findViewById(R.id.tvTxId); tvTxAddress = view.findViewById(R.id.tvTxAddress); - tvTxPaymentId = view.findViewById(R.id.tvTxPaymentId); tvTxAmount = view.findViewById(R.id.tvTxAmount); tvTxFee = view.findViewById(R.id.tvTxFee); @@ -150,9 +152,11 @@ public void onResumeFragment() { NumberFormat df = NumberFormat.getInstance(Locale.US); df.setMaximumFractionDigits(12); String btcAmount = df.format(btcData.getBtcAmount()); - tvXmrToAmount.setText(getString(R.string.info_send_xmrto_success_btc, btcAmount)); + tvXmrToAmount.setText(getString(R.string.info_send_xmrto_success_btc, btcAmount, btcData.getBtcSymbol())); //TODO btcData.getBtcAddress(); tvTxXmrToKey.setText(btcData.getXmrtoOrderId()); + final Crypto crypto = Crypto.withSymbol(btcData.getBtcSymbol()); + ivXmrToIcon.setImageResource(crypto.getIconEnabledId()); tvXmrToSupport.setOnClickListener(v -> { Uri orderUri = getXmrToApi().getQueryOrderUri(btcData.getXmrtoOrderId()); Intent intent = new Intent(Intent.ACTION_VIEW, orderUri); @@ -211,7 +215,7 @@ void showXmrToStatus(final QueryOrderStatus status) { statusResource = R.drawable.ic_error_red_24dp; pbXmrto.getIndeterminateDrawable().setColorFilter(0xff8b0000, android.graphics.PorterDuff.Mode.MULTIPLY); } else if (status.isSent() || status.isPaid()) { - tvXmrToStatus.setText(getString(R.string.info_send_xmrto_sent)); + tvXmrToStatus.setText(getString(R.string.info_send_xmrto_sent, btcData.getBtcSymbol())); statusResource = R.drawable.ic_success_green_24dp; pbXmrto.getIndeterminateDrawable().setColorFilter(0xFF417505, android.graphics.PorterDuff.Mode.MULTIPLY); } else if (status.isWaiting()) { @@ -228,6 +232,7 @@ void showXmrToStatus(final QueryOrderStatus status) { ivXmrToStatus.setImageResource(statusResource); if (status.isTerminal()) { pbXmrto.setVisibility(View.INVISIBLE); + ivXmrToIcon.setVisibility(View.GONE); ivXmrToStatus.setVisibility(View.GONE); ivXmrToStatusBig.setImageResource(statusResource); ivXmrToStatusBig.setVisibility(View.VISIBLE); @@ -241,7 +246,7 @@ private SideShiftApi getXmrToApi() { synchronized (this) { if (xmrToApi == null) { xmrToApi = new SideShiftApiImpl(OkHttpHelper.getOkHttpClient(), - Helper.getXmrToBaseUrl()); + ServiceHelper.getXmrToBaseUrl()); } } } diff --git a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendFragment.java b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendFragment.java index 2e0faf5225..903aff0f96 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendFragment.java @@ -29,6 +29,7 @@ import android.widget.Button; import android.widget.EditText; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -92,8 +93,6 @@ public interface Listener { void setOnUriScannedListener(OnUriScannedListener onUriScannedListener); } - private EditText etDummy; - private View llNavBar; private DotBar dotBar; private Button bPrev; @@ -101,7 +100,7 @@ public interface Listener { private Button bDone; - static private int MAX_FALLBACK = Integer.MAX_VALUE; + static private final int MAX_FALLBACK = Integer.MAX_VALUE; public static SendFragment newInstance(String uri) { SendFragment f = new SendFragment(); @@ -166,28 +165,18 @@ public void onPageScrollStateChanged(int state) { } }); - bPrev.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - spendViewPager.previous(); - } - }); + bPrev.setOnClickListener(v -> spendViewPager.previous()); - bNext.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - spendViewPager.next(); - } - }); + bNext.setOnClickListener(v -> spendViewPager.next()); - bDone.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - Timber.d("bDone.onClick"); - activityCallback.onFragmentDone(); - } + bDone.setOnClickListener(v -> { + Timber.d("bDone.onClick"); + activityCallback.onFragmentDone(); }); updatePosition(0); - etDummy = view.findViewById(R.id.etDummy); + final EditText etDummy = view.findViewById(R.id.etDummy); etDummy.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); etDummy.requestFocus(); Helper.hideKeyboard(getActivity()); @@ -197,7 +186,7 @@ public void onClick(View v) { String uri = args.getString(WalletActivity.REQUEST_URI); Timber.d("URI: %s", uri); if (uri != null) { - barcodeData = BarcodeData.fromQrCode(uri); + barcodeData = BarcodeData.fromString(uri); Timber.d("barcodeData: %s", barcodeData != null ? barcodeData.toString() : "null"); } } @@ -236,7 +225,7 @@ public void onResume() { } @Override - public void onAttach(Context context) { + public void onAttach(@NonNull Context context) { Timber.d("onAttach %s", context); super.onAttach(context); if (context instanceof Listener) { @@ -300,12 +289,7 @@ public void setMode(Mode aMode) { default: throw new IllegalArgumentException("Mode " + String.valueOf(aMode) + " unknown!"); } - getView().post(new Runnable() { - @Override - public void run() { - pagerAdapter.notifyDataSetChanged(); - } - }); + getView().post(() -> pagerAdapter.notifyDataSetChanged()); Timber.d("New Mode = %s", mode.toString()); } } @@ -338,8 +322,9 @@ public int getCount() { return numPages; } + @NonNull @Override - public Object instantiateItem(ViewGroup container, int position) { + public Object instantiateItem(@NonNull ViewGroup container, int position) { Timber.d("instantiateItem %d", position); SendWizardFragment fragment = (SendWizardFragment) super.instantiateItem(container, position); myFragments.put(position, new WeakReference<>(fragment)); @@ -347,20 +332,21 @@ public Object instantiateItem(ViewGroup container, int position) { } @Override - public void destroyItem(ViewGroup container, int position, Object object) { + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { Timber.d("destroyItem %d", position); myFragments.remove(position); super.destroyItem(container, position, object); } public SendWizardFragment getFragment(int position) { - WeakReference ref = myFragments.get(position); + WeakReference ref = myFragments.get(position); if (ref != null) return myFragments.get(position).get(); else return null; } + @NonNull @Override public SendWizardFragment getItem(int position) { Timber.d("getItem(%d) CREATE", position); @@ -415,7 +401,7 @@ public CharSequence getPageTitle(int position) { } @Override - public int getItemPosition(Object object) { + public int getItemPosition(@NonNull Object object) { Timber.d("getItemPosition %s", String.valueOf(object)); if (object instanceof SendAddressWizardFragment) { // keep these pages diff --git a/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java b/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java index d90bb63f12..9d2d8ba2cf 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java +++ b/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java @@ -17,18 +17,20 @@ package com.m2049r.xmrwallet.layout; import android.content.Context; -import androidx.core.content.ContextCompat; -import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.RecyclerView; + import com.m2049r.xmrwallet.R; +import com.m2049r.xmrwallet.data.Crypto; +import com.m2049r.xmrwallet.data.UserNotes; import com.m2049r.xmrwallet.model.TransactionInfo; import com.m2049r.xmrwallet.util.Helper; -import com.m2049r.xmrwallet.data.UserNotes; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -141,7 +143,13 @@ void bind(int position) { UserNotes userNotes = new UserNotes(infoItem.notes); if (userNotes.xmrtoKey != null) { - ivTxType.setVisibility(View.VISIBLE); + final Crypto crypto = Crypto.withSymbol(userNotes.xmrtoCurrency); + if (crypto != null) { + ivTxType.setImageResource(crypto.getIconEnabledId()); + ivTxType.setVisibility(View.VISIBLE); + } else {// otherwirse pretend we don't know it's a shift + ivTxType.setVisibility(View.GONE); + } } else { ivTxType.setVisibility(View.GONE); // gives us more space for the amount } diff --git a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/api/CreateOrder.java b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/api/CreateOrder.java index e36e2eaf0a..f738956b73 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/api/CreateOrder.java +++ b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/api/CreateOrder.java @@ -21,6 +21,8 @@ public interface CreateOrder { String TAG = "side"; + String getBtcCurrency(); + double getBtcAmount(); String getBtcAddress(); diff --git a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/api/SideShiftApi.java b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/api/SideShiftApi.java index 1bad6cc01a..6c9331c9a0 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/api/SideShiftApi.java +++ b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/api/SideShiftApi.java @@ -23,8 +23,6 @@ import com.m2049r.xmrwallet.service.shift.ShiftCallback; public interface SideShiftApi { - - String ASSET = "btc"; int QUERY_INTERVAL = 5000; // ms /** diff --git a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/CreateOrderImpl.java b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/CreateOrderImpl.java index d209c40e2c..258cf4d71c 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/CreateOrderImpl.java +++ b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/CreateOrderImpl.java @@ -25,6 +25,7 @@ import com.m2049r.xmrwallet.service.shift.sideshift.api.CreateOrder; import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi; import com.m2049r.xmrwallet.util.DateHelper; +import com.m2049r.xmrwallet.util.ServiceHelper; import org.json.JSONException; import org.json.JSONObject; @@ -35,6 +36,8 @@ import lombok.Getter; class CreateOrderImpl implements CreateOrder { + @Getter + private final String btcCurrency; @Getter private final double btcAmount; @Getter @@ -56,9 +59,10 @@ class CreateOrderImpl implements CreateOrder { // sanity checks final String depositMethod = jsonObject.getString("depositMethodId"); final String settleMethod = jsonObject.getString("settleMethodId"); - if (!"xmr".equals(depositMethod) || !SideShiftApi.ASSET.equals(settleMethod)) + if (!"xmr".equals(depositMethod) || !ServiceHelper.ASSET.equals(settleMethod)) throw new IllegalStateException(); + btcCurrency = settleMethod.toUpperCase(); btcAmount = jsonObject.getDouble("settleAmount"); JSONObject settleAddress = jsonObject.getJSONObject("settleAddress"); btcAddress = settleAddress.getString("address"); diff --git a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/QueryOrderParametersImpl.java b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/QueryOrderParametersImpl.java index a1bf31c92f..afa5527c52 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/QueryOrderParametersImpl.java +++ b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/QueryOrderParametersImpl.java @@ -23,6 +23,7 @@ import com.m2049r.xmrwallet.service.shift.sideshift.api.QueryOrderParameters; import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi; import com.m2049r.xmrwallet.service.shift.ShiftCallback; +import com.m2049r.xmrwallet.util.ServiceHelper; import org.json.JSONException; import org.json.JSONObject; @@ -53,7 +54,7 @@ public double getUpperLimit() { public static void call(@NonNull final ShiftApiCall api, @NonNull final ShiftCallback callback) { - api.call("pairs/xmr/" + SideShiftApi.ASSET, new NetworkCallback() { + api.call("pairs/xmr/" + ServiceHelper.ASSET, new NetworkCallback() { @Override public void onSuccess(JSONObject jsonObject) { try { diff --git a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/RequestQuoteImpl.java b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/RequestQuoteImpl.java index 91addc5613..6a1b80233b 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/RequestQuoteImpl.java +++ b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/RequestQuoteImpl.java @@ -24,6 +24,7 @@ import com.m2049r.xmrwallet.service.shift.sideshift.api.RequestQuote; import com.m2049r.xmrwallet.service.shift.sideshift.api.SideShiftApi; import com.m2049r.xmrwallet.service.shift.ShiftCallback; +import com.m2049r.xmrwallet.util.ServiceHelper; import org.json.JSONException; import org.json.JSONObject; @@ -55,7 +56,7 @@ class RequestQuoteImpl implements RequestQuote { // sanity checks final String depositMethod = jsonObject.getString("depositMethod"); final String settleMethod = jsonObject.getString("settleMethod"); - if (!"xmr".equals(depositMethod) || !SideShiftApi.ASSET.equals(settleMethod)) + if (!"xmr".equals(depositMethod) || !ServiceHelper.ASSET.equals(settleMethod)) throw new IllegalStateException(); btcAmount = jsonObject.getDouble("settleAmount"); @@ -106,7 +107,7 @@ public void onError(Exception ex) { static JSONObject createRequest(final double xmrAmount) throws JSONException { final JSONObject jsonObject = new JSONObject(); jsonObject.put("depositMethod", "xmr"); - jsonObject.put("settleMethod", SideShiftApi.ASSET); + jsonObject.put("settleMethod", ServiceHelper.ASSET); // #sideshift is silly and likes numbers as strings String amount = AmountFormatter.format(xmrAmount); jsonObject.put("depositAmount", amount); diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java b/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java index 326da62597..66a370452e 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java +++ b/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java @@ -323,15 +323,6 @@ static public Animation getShakeAnimation(Context context) { return ShakeAnimation; } - static public HttpUrl getXmrToBaseUrl() { - if ((WalletManager.getInstance() == null) - || (WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet)) { - throw new IllegalStateException("Only mainnet not supported"); - } else { - return HttpUrl.parse("https://sideshift.ai/api/v1/"); - } - } - private final static char[] HexArray = "0123456789ABCDEF".toCharArray(); public static String bytesToHex(byte[] data) { @@ -639,10 +630,6 @@ static private boolean processPasswordEntry(Context context, String walletName, } } - static public ExchangeApi getExchangeApi() { - return new com.m2049r.xmrwallet.service.exchange.krakenEcb.ExchangeApiImpl(OkHttpHelper.getOkHttpClient()); - } - public interface Action { boolean run(); } diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/OpenAliasHelper.java b/app/src/main/java/com/m2049r/xmrwallet/util/OpenAliasHelper.java index 4b9c784c30..b710fbc891 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/util/OpenAliasHelper.java +++ b/app/src/main/java/com/m2049r/xmrwallet/util/OpenAliasHelper.java @@ -21,6 +21,7 @@ import android.os.AsyncTask; import com.m2049r.xmrwallet.data.BarcodeData; +import com.m2049r.xmrwallet.data.Crypto; import org.jitsi.dnssec.validator.ValidatingResolver; import org.xbill.DNS.DClass; @@ -52,7 +53,6 @@ public class OpenAliasHelper { public static final String OA1_NAME = "recipient_name"; public static final String OA1_DESCRIPTION = "tx_description"; public static final String OA1_AMOUNT = "tx_amount"; - public static final String OA1_PAYMENTID = "tx_payment_id"; public static final int DNS_LOOKUP_TIMEOUT = 2500; // ms @@ -65,7 +65,7 @@ public static Map parse(String oaString) { } public interface OnResolvedListener { - void onResolved(Map dataMap); + void onResolved(Map dataMap); void onFailure(); } @@ -138,7 +138,7 @@ protected Boolean doInBackground(String... args) { public void onPostExecute(Boolean success) { if (resolvedListener != null) if (success) { - Map dataMap = new HashMap<>(); + Map dataMap = new HashMap<>(); for (String txt : txts) { BarcodeData bc = BarcodeData.parseOpenAlias(txt, dnssec); if (bc != null) { diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/ServiceHelper.java b/app/src/main/java/com/m2049r/xmrwallet/util/ServiceHelper.java new file mode 100644 index 0000000000..6221682ba9 --- /dev/null +++ b/app/src/main/java/com/m2049r/xmrwallet/util/ServiceHelper.java @@ -0,0 +1,24 @@ +package com.m2049r.xmrwallet.util; + +import com.m2049r.xmrwallet.model.NetworkType; +import com.m2049r.xmrwallet.model.WalletManager; +import com.m2049r.xmrwallet.service.exchange.api.ExchangeApi; + +import okhttp3.HttpUrl; + +public class ServiceHelper { + public static String ASSET = null; + + static public HttpUrl getXmrToBaseUrl() { + if ((WalletManager.getInstance() == null) + || (WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet)) { + throw new IllegalStateException("Only mainnet not supported"); + } else { + return HttpUrl.parse("https://sideshift.ai/api/v1/"); + } + } + + static public ExchangeApi getExchangeApi() { + return new com.m2049r.xmrwallet.service.exchange.krakenEcb.ExchangeApiImpl(OkHttpHelper.getOkHttpClient()); + } +} diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/validator/BitcoinAddressType.java b/app/src/main/java/com/m2049r/xmrwallet/util/validator/BitcoinAddressType.java new file mode 100644 index 0000000000..a1415b1e62 --- /dev/null +++ b/app/src/main/java/com/m2049r/xmrwallet/util/validator/BitcoinAddressType.java @@ -0,0 +1,51 @@ +package com.m2049r.xmrwallet.util.validator; + +import lombok.Getter; + +public enum BitcoinAddressType { + BTC(Type.BTC, Type.BTC_BECH32_PREFIX), + LTC(Type.LTC, Type.LTC_BECH32_PREFIX), + DASH(Type.DASH, null), + DOGE(Type.DOGE, null); + + @Getter + private final byte[] production; + @Getter + private final byte[] testnet; + + @Getter + private final String productionBech32Prefix; + @Getter + private final String testnetBech32Prefix; + + public boolean hasBech32() { + return productionBech32Prefix != null; + } + + public String getBech32Prefix(boolean testnet) { + return testnet ? testnetBech32Prefix : productionBech32Prefix; + } + + BitcoinAddressType(byte[][] types, String[] bech32Prefix) { + production = types[0]; + testnet = types[1]; + if (bech32Prefix != null) { + productionBech32Prefix = bech32Prefix[0]; + testnetBech32Prefix = bech32Prefix[1]; + } else { + productionBech32Prefix = null; + testnetBech32Prefix = null; + } + } + + // Java is silly and doesn't allow array initializers in the construction + private static class Type { + private static final byte[][] BTC = {{0x00, 0x05}, {0x6f, (byte) 0xc4}}; + private static final String[] BTC_BECH32_PREFIX = {"bc", "tb"}; + private static final byte[][] LTC = {{0x30, 0x05, 0x32}, {0x6f, (byte) 0xc4, 0x3a}}; + private static final String[] LTC_BECH32_PREFIX = {"ltc", "tltc"}; + private static final byte[][] DASH = {{0x4c, 0x10}, {(byte) 0x8c, 0x13}}; + private static final byte[][] DOGE = {{0x1e, 0x16}, {0x71, (byte) 0xc4}}; + } + +} diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/BitcoinAddressValidator.java b/app/src/main/java/com/m2049r/xmrwallet/util/validator/BitcoinAddressValidator.java similarity index 74% rename from app/src/main/java/com/m2049r/xmrwallet/util/BitcoinAddressValidator.java rename to app/src/main/java/com/m2049r/xmrwallet/util/validator/BitcoinAddressValidator.java index 76fa897956..ce5cec0448 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/util/BitcoinAddressValidator.java +++ b/app/src/main/java/com/m2049r/xmrwallet/util/validator/BitcoinAddressValidator.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.m2049r.xmrwallet.util; +package com.m2049r.xmrwallet.util.validator; // mostly based on https://rosettacode.org/wiki/Bitcoin/address_validation#Java +import com.m2049r.xmrwallet.data.Crypto; import com.m2049r.xmrwallet.model.NetworkType; import com.m2049r.xmrwallet.model.WalletManager; @@ -28,28 +29,47 @@ import java.util.Arrays; public class BitcoinAddressValidator { - private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - public static boolean validate(String addrress) { - boolean testnet = WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet; - if (validate(addrress, testnet)) return true; - return validateBech32Segwit(addrress, testnet); + public static Crypto validate(String address) { + for (BitcoinAddressType type : BitcoinAddressType.values()) { + if (validate(address, type)) + return Crypto.valueOf(type.name()); + } + return null; + } + + // just for tests + public static boolean validateBTC(String addrress, boolean testnet) { + return validate(addrress, BitcoinAddressType.BTC, testnet); + } + + public static boolean validate(String addrress, BitcoinAddressType type, boolean testnet) { + if (validate(addrress, testnet ? type.getTestnet() : type.getProduction())) + return true; + if (type.hasBech32()) + return validateBech32Segwit(addrress, type, testnet); + else + return false; } - public static boolean validate(String addrress, boolean testnet) { + public static boolean validate(String addrress, BitcoinAddressType type) { + final boolean testnet = WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet; + return validate(addrress, type, testnet); + } + + public static boolean validate(String addrress, byte[] addressTypes) { if (addrress.length() < 26 || addrress.length() > 35) return false; byte[] decoded = decodeBase58To25Bytes(addrress); if (decoded == null) return false; - int v = decoded[0] & 0xFF; - if (!testnet) { - if ((v != 0x00) && (v != 0x05)) return false; - } else { - if ((v != 0x6f) && (v != 0xc4)) return false; + boolean nok = true; + for (byte b : addressTypes) { + nok = nok && (v != (b & 0xFF)); } + if (nok) return false; byte[] hash1 = sha256(Arrays.copyOfRange(decoded, 0, 21)); byte[] hash2 = sha256(hash1); @@ -95,18 +115,20 @@ private static byte[] sha256(byte[] data) { private static final String DATA_CHARS = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; - public static boolean validateBech32Segwit(String bech32, boolean testnet) { + public static boolean validateBech32Segwit(String bech32, BitcoinAddressType type, boolean testnet) { if (!bech32.equals(bech32.toLowerCase()) && !bech32.equals(bech32.toUpperCase())) { return false; // mixing upper and lower case not allowed } bech32 = bech32.toLowerCase(); - if (testnet && !bech32.startsWith("tb1")) return false; - if (!testnet && !bech32.startsWith("bc1")) return false; + if (!bech32.startsWith(type.getBech32Prefix(testnet))) return false; + + final int hrpLength = type.getBech32Prefix(testnet).length(); - if ((bech32.length() < 14) || (bech32.length() > 74)) return false; - int mod = bech32.length() % 8; - if ((mod == 0) || (mod == 3) || (mod == 5)) return false; + if ((bech32.length() < (12 + hrpLength)) || (bech32.length() > (72 + hrpLength))) + return false; + int mod = (bech32.length() - hrpLength) % 8; + if ((mod == 6) || (mod == 1) || (mod == 3)) return false; int sep = -1; final byte[] bytes = bech32.getBytes(StandardCharsets.US_ASCII); @@ -117,7 +139,7 @@ public static boolean validateBech32Segwit(String bech32, boolean testnet) { if (bytes[i] == 49) sep = i; // 49 := '1' in ASCII } - if (sep != 2) return false; // bech32 always has len(hrp)==2 + if (sep != hrpLength) return false; if (sep > bytes.length - 7) { return false; // min 6 bytes data } @@ -158,12 +180,12 @@ private static int polymod(byte[] values) { private static byte[] hrpExpand(byte[] hrp) { final byte[] expanded = new byte[(2 * hrp.length) + 1]; int i = 0; - for (int j = 0; j < hrp.length; j++) { - expanded[i++] = (byte) (hrp[j] >> 5); + for (byte b : hrp) { + expanded[i++] = (byte) (b >> 5); } expanded[i++] = 0; - for (int j = 0; j < hrp.length; j++) { - expanded[i++] = (byte) (hrp[j] & 0x1f); + for (byte b : hrp) { + expanded[i++] = (byte) (b & 0x1f); } return expanded; } @@ -195,4 +217,4 @@ private static boolean validateBech32Data(final byte[] data) { return true; } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/validator/EthAddressValidator.java b/app/src/main/java/com/m2049r/xmrwallet/util/validator/EthAddressValidator.java new file mode 100644 index 0000000000..3e4c47636e --- /dev/null +++ b/app/src/main/java/com/m2049r/xmrwallet/util/validator/EthAddressValidator.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017 m2049r er al. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.m2049r.xmrwallet.util.validator; + +// mostly based on https://github.com/ognus/wallet-address-validator/blob/master/src/ethereum_validator.js + +import com.theromus.sha.Keccak; +import com.theromus.sha.Parameters; + +import java.nio.charset.StandardCharsets; +import java.util.regex.Pattern; + +public class EthAddressValidator { + static private final Pattern ETH_ADDRESS = Pattern.compile("^0x[0-9a-fA-F]{40}$"); + static private final Pattern ETH_ALLLOWER = Pattern.compile("^0x[0-9a-f]{40}$"); + static private final Pattern ETH_ALLUPPER = Pattern.compile("^0x[0-9A-F]{40}$"); + + public static boolean validate(String address) { + // Check if it has the basic requirements of an address + if (!ETH_ADDRESS.matcher(address).matches()) + return false; + + // If it's all small caps or all all caps, return true + if (ETH_ALLLOWER.matcher(address).matches() || ETH_ALLUPPER.matcher(address).matches()) { + return true; + } + + // Otherwise check each case + return validateChecksum(address); + } + + private static boolean validateChecksum(String address) { + // Check each case + address = address.substring(2); // strip 0x + + Keccak keccak = new Keccak(); + final byte[] addressHash = keccak.getHash( + address.toLowerCase().getBytes(StandardCharsets.US_ASCII), + Parameters.KECCAK_256); + for (int i = 0; i < 40; i++) { + boolean upper = (addressHash[i / 2] & ((i % 2) == 0 ? 128 : 8)) != 0; + char c = address.charAt(i); + if (Character.isAlphabetic(c)) { + if (Character.isUpperCase(c) && !upper) return false; + if (Character.isLowerCase(c) && upper) return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeEditText.java b/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeEditText.java index a85900f5f1..6602cb79da 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeEditText.java +++ b/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeEditText.java @@ -40,6 +40,7 @@ import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback; import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate; import com.m2049r.xmrwallet.util.Helper; +import com.m2049r.xmrwallet.util.ServiceHelper; import java.util.ArrayList; import java.util.Arrays; @@ -184,6 +185,12 @@ void setInitialSpinnerSelections(Spinner baseSpinner, Spinner quoteSpinner) { private boolean isInitialized = false; + void postInitialize() { + setInitialSpinnerSelections(sCurrencyA, sCurrencyB); + isInitialized = true; + startExchange(); + } + @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -212,14 +219,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { setCurrencyAdapter(sCurrencyA); setCurrencyAdapter(sCurrencyB); - post(new Runnable() { - @Override - public void run() { - setInitialSpinnerSelections(sCurrencyA, sCurrencyB); - isInitialized = true; - startExchange(); - } - }); + post(this::postInitialize); // make progress circle gray pbExchange.getIndeterminateDrawable(). @@ -296,7 +296,7 @@ public void doExchange() { } } - private final ExchangeApi exchangeApi = Helper.getExchangeApi(); + private final ExchangeApi exchangeApi = ServiceHelper.getExchangeApi(); // starts exchange through exchange api void startExchange() { diff --git a/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeOtherEditText.java b/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeOtherEditText.java index 3b57d07ec7..3dd344ef73 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeOtherEditText.java +++ b/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeOtherEditText.java @@ -25,6 +25,8 @@ import android.util.AttributeSet; import android.widget.Spinner; +import androidx.annotation.NonNull; + import com.m2049r.xmrwallet.R; import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback; import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate; @@ -46,12 +48,15 @@ public class ExchangeOtherEditText extends ExchangeEditText { public void setExchangeRate(double rate) { exchangeRate = rate; - post(new Runnable() { - @Override - public void run() { - startExchange(); - } - }); + post(this::startExchange); + } + + public void setBaseCurrency(@NonNull String symbol) { + if (symbol.equals(baseCurrency)) return; + baseCurrency = symbol; + setCurrencyAdapter(sCurrencyA); + setCurrencyAdapter(sCurrencyB); + post(this::postInitialize); } private void setBaseCurrency(Context context, AttributeSet attrs) { @@ -184,12 +189,7 @@ public double getRate() { @Override public void onError(final Exception e) { Timber.e(e.getLocalizedMessage()); - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - exchangeFailed(); - } - }); + new Handler(Looper.getMainLooper()).post(() -> exchangeFailed()); } }); } diff --git a/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeView.java b/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeView.java index dceb376ac4..b35a0b6acd 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeView.java +++ b/app/src/main/java/com/m2049r/xmrwallet/widget/ExchangeView.java @@ -44,6 +44,7 @@ import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate; import com.m2049r.xmrwallet.util.ColorHelper; import com.m2049r.xmrwallet.util.Helper; +import com.m2049r.xmrwallet.util.ServiceHelper; import java.util.ArrayList; import java.util.Arrays; @@ -311,7 +312,7 @@ private void clearAmounts() { } } - private final ExchangeApi exchangeApi = Helper.getExchangeApi(); + private final ExchangeApi exchangeApi = ServiceHelper.getExchangeApi(); void startExchange() { showProgress(); diff --git a/app/src/main/res/drawable/ic_monero.xml b/app/src/main/res/drawable/ic_monero.xml new file mode 100644 index 0000000000..b50ba67181 --- /dev/null +++ b/app/src/main/res/drawable/ic_monero.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_monero_bw.xml b/app/src/main/res/drawable/ic_monero_bw.xml new file mode 100644 index 0000000000..1b4cef11c2 --- /dev/null +++ b/app/src/main/res/drawable/ic_monero_bw.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_sideshift_circle.xml b/app/src/main/res/drawable/ic_sideshift_circle.xml new file mode 100644 index 0000000000..366f959db3 --- /dev/null +++ b/app/src/main/res/drawable/ic_sideshift_circle.xml @@ -0,0 +1,12 @@ + + > + + diff --git a/app/src/main/res/drawable/ic_sideshift_white.xml b/app/src/main/res/drawable/ic_sideshift_white.xml index 7d8a3284a8..76d8891bba 100644 --- a/app/src/main/res/drawable/ic_sideshift_white.xml +++ b/app/src/main/res/drawable/ic_sideshift_white.xml @@ -3,46 +3,46 @@ android:height="80dp" android:viewportWidth="648" android:viewportHeight="80"> - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_32dp.png b/app/src/main/res/drawable/ic_xmrto_32dp.png deleted file mode 100644 index b9cec90cd6fdd7c503de928ed9b03d36a1d8a336..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1898 zcmV-w2bK7VP)EvOw;vEyuL=x+fN;b*e-MjbpoNx2pz1dyr zo7wNY&pqGcobN0^>rghwG!n{adOW|EE|2O1`h$xA4XJ$__12+jKAmf1XJ_k6yW|3R zo5=t`*|TzsvMDx^a7Olo*ao7qs(_V<4%=@K0A+J`kT$B;GqO)MajjHskZ zNj$oJiDwNV|Ae5>($=`lQGt=35Ilm$-UwzONLC%0b~jeSy>i);77IDZAC!T8(OsnV z9{QG^(UPuu+Sw+442Dws7|`mk1MA!u6wOo1cZ$rV#D!o-$QT3GDGu~U6~qRK&p1t+ zI*lvQcKWXUf=Ye3h?SLjUKM?os=97$Ev#8I=>WE$O8%O zlC2wA@MUsSoNzDX#zp-eQs9CYShnD>)wujs21N)NHhlDoBA8}K4y0a*pf}tG{oz%U zh?StD;fziIjrkRzd*eCs9Vi7G3`KF51Vh={6VKYqNesV1a((8wAcO>I&&kNxcjT$% zIehKP_kF;=@D^A{tmGzmIXXz}h3+++GEH=0>0HFu)l>c@%X9dZ1@*7hhPMAg<2nou zBIG~}I+ox;CqV-beH*_Ch_G4j&#J1gukR5~+4f!`c=k_dBcfwuskiFd93yEsozCdg z)YJ;4Md?7a`To-v@uDsyz8E16NZ>tpG|~HOPKJ8t(hys}h8ob}xZJhl5;px(Ak|tu zv~l1*v@T02-0I)rRt57#Lggko?zt{(LZy-Uh6C5Kp;f-e&X7GYJ81QZ86qXfY1RDr zdA2lVPbdy&EDWq~XA6`=4Yc!mVQ-lTNq0G;)jL;)*+$N2qZA+*So)`cWzYh!44iMU z-PfBR5+OA%A5|f^;^GLJpnXv_FiQkPj93A>^2iY3#c8MS8(@=kcMCr*AqnS1*%=R> z!g*jDy8+|{{yIzg?tA}!Yg7#3fMAFdr5>~!M?u$AjD|1Wug+j>h=YwAHgcia2~|1z zG06(*-`o7geAc^#I4CVGg*9u|7*5pkT|5+zF$iWzEhz|Mv^AZb}?nc+k|vz{Ah zw}0bMiXO}%pLA(06_l+=ED+q}8Oh*sxj5+<>VOq1RtOP?UQBHt)(0B&Hdrx17UH94 zI8c;8Wur*Er@zF!wSac#576r?O)n4QMS)*s%D}mE=GJnzLDSD)B!XJ977M3llK9^h zV(>kPii)bs*_G4Hq+y_H@mImdR7_)qg0YF@q~LG?8$WKm`J99v)&B-6B2adU!zxedp%mTS+~(GjUbt+fk72#rEwhL$s#<1$!FbpJ=%dXWXCI^_4K@g- z!vzqmgX=7@OA%AU1=A(~`fyWL(wV1~mSE@47J#r~)fmW|=0J=ybRYaWtKpNOwe)eR zeP?0u%rIi?MxL%x>_}iy31CY;36=pfgY5Ml)RVMq>YgP8JOJg#$Mh{WveLwcitf*(ssPT|#ARaMRqfyk56Ijv#a z=l%UtUa_o07Gs093oI{>;WA&bb3j4f^Mo-lVU$2h?9>J*_0dXp2}x%7?&dPu64a@S5T@M4 zpS*eF=Kq#o;fSEGd?!Rq%;hZ4{)wPJG53WPE0Nb9v^GaILa% zVTR`J*US&aS+xXgf@mp)obP}j2*$?7o+p4iBIo7hWghtHz*3*j7xrk(cHwZ^Y8}{m zdt79;SaGmk$PNT62pR*j6&DweK3{%*a%E*@f9HK?Op~iAX7`w4RAH3L)W%=N9wT4w kI_w0SzCWau7rxB!KdEF6UhpX;_y7O^07*qoM6N<$f>I-pZ2$lO diff --git a/app/src/main/res/drawable/ic_xmrto_btc.xml b/app/src/main/res/drawable/ic_xmrto_btc.xml new file mode 100644 index 0000000000..60efbe25a9 --- /dev/null +++ b/app/src/main/res/drawable/ic_xmrto_btc.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_btc_off.xml b/app/src/main/res/drawable/ic_xmrto_btc_off.xml new file mode 100644 index 0000000000..5a49d3da37 --- /dev/null +++ b/app/src/main/res/drawable/ic_xmrto_btc_off.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_dash.xml b/app/src/main/res/drawable/ic_xmrto_dash.xml new file mode 100644 index 0000000000..a3ace1576e --- /dev/null +++ b/app/src/main/res/drawable/ic_xmrto_dash.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_dash_off.xml b/app/src/main/res/drawable/ic_xmrto_dash_off.xml new file mode 100644 index 0000000000..28a712fda0 --- /dev/null +++ b/app/src/main/res/drawable/ic_xmrto_dash_off.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_doge.xml b/app/src/main/res/drawable/ic_xmrto_doge.xml new file mode 100644 index 0000000000..c8bfcd789e --- /dev/null +++ b/app/src/main/res/drawable/ic_xmrto_doge.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_doge_off.xml b/app/src/main/res/drawable/ic_xmrto_doge_off.xml new file mode 100644 index 0000000000..51f0639a0a --- /dev/null +++ b/app/src/main/res/drawable/ic_xmrto_doge_off.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_eth.xml b/app/src/main/res/drawable/ic_xmrto_eth.xml new file mode 100644 index 0000000000..9569125fee --- /dev/null +++ b/app/src/main/res/drawable/ic_xmrto_eth.xml @@ -0,0 +1,38 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_eth_off.xml b/app/src/main/res/drawable/ic_xmrto_eth_off.xml new file mode 100644 index 0000000000..04da5f010f --- /dev/null +++ b/app/src/main/res/drawable/ic_xmrto_eth_off.xml @@ -0,0 +1,38 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_ltc.xml b/app/src/main/res/drawable/ic_xmrto_ltc.xml new file mode 100644 index 0000000000..5bb3470a87 --- /dev/null +++ b/app/src/main/res/drawable/ic_xmrto_ltc.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_ltc_off.xml b/app/src/main/res/drawable/ic_xmrto_ltc_off.xml new file mode 100644 index 0000000000..663c247616 --- /dev/null +++ b/app/src/main/res/drawable/ic_xmrto_ltc_off.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_xmrto_whitestroke_24px.png b/app/src/main/res/drawable/ic_xmrto_whitestroke_24px.png deleted file mode 100644 index a1650c38171aa66f39a35c9c03285e286314d731..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1310 zcmV+(1>yRMP)I;$0jx$yhy)PiA`n0zMCDR#EmV4XIk!1yX8ACkim?!U@K5GpX0QGKYpuQK zU+_OeiOAj7%YdhVa-c7e4=5l8GysQzeZby3GKffb&oB|$D)){$5t-T@S9cXG1U>?E z0Q=%$tb^Ne8m}Q84HzW}RBjk$M$rb(!5F>(%sg*zHL&V#Em{a{0dRi1NOIe2WRBN? z89@0XsE{9XXa;-^VryVqs6YhYsF%>omU|o@153IScoz5+AhZ7yI^JK5GIg|G#qMer z@CoK{8?kOcDuoIcfo&m5NAEu#^NDSs831nrZ{03X1pEjTW>4&fkI{IK# zDyC{)_L(EQz_L&VNIV9BIejTPudH)Ll1Wes90vev_dGHOt5Lm1;9qg)y!Q z`|J*IY_Q_q_MQgN3&6g99u+Qd1v-&PBngFr_-8DGbb`dzl}JYmDt`olN)-)uW^e93GkO6{PD2mg1gWGZX%o$D`J4WU5O8j%GP=ya5$quCXB&v5A`mkqQ z^5&n&99o6S$paLqt`685a1B5!D#gB9kJF5Ms6ZqVVfE_OY~H-tZCCj`w1PgQYp0Q{ zF2Smu239*-xEOuFR3znQu6!X+phLrTMEp}CGj?rSQ{1R`T_5AjRx!iz6XeB92#2Mu^dPylQcIs0}u=b zDeP0s?p}nked5gk@Re7>Tz*^gj2TrgZ&edw}b= zyXkj8MJyJhY;+k)DT<4W357y9jzhcUqfo!ehfgMn4x3Es%yuN+gfer%2qI!*PF{;X zY(BsR+-Vs1%nsm1;8HXi<;c+^Oqw)_#>PfcsT8`d0|LPwNb5B?R0G)*DyKK16c{G{ zDeF9P2Y4EY!@md4L%^575D}s7t2%0HYe^=Pq?`b~LTT1LdVy##P0G?xz8v&EW6;OF zj>_u?VBtE$`7Xw8=4hUXZ2J%M*u#Di8FDW(*~4Psaa=PD-XSIp{LpzxYPt*f3$~)g Ur6R0sb^rhX07*qoM6N<$f-=ENwEzGB diff --git a/app/src/main/res/layout/fragment_send_address.xml b/app/src/main/res/layout/fragment_send_address.xml index ded4ab8f7a..29dcfcba77 100644 --- a/app/src/main/res/layout/fragment_send_address.xml +++ b/app/src/main/res/layout/fragment_send_address.xml @@ -29,14 +29,12 @@ android:orientation="horizontal"> - - - - + android:layout_height="wrap_content" + android:orientation="vertical"> + android:weightSum="6"> - + android:layout_weight="1" + android:background="@null" + android:padding="8dp" + android:src="@drawable/ic_monero" /> - + + + android:layout_weight="1" + android:background="@null" + android:padding="8dp" + android:src="@drawable/ic_xmrto_ltc_off" /> + + + + + + - + + + diff --git a/app/src/main/res/layout/fragment_send_btc_amount.xml b/app/src/main/res/layout/fragment_send_btc_amount.xml index 00e5a7d862..fd1b9f8be7 100644 --- a/app/src/main/res/layout/fragment_send_btc_amount.xml +++ b/app/src/main/res/layout/fragment_send_btc_amount.xml @@ -12,7 +12,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:gravity="center" + android:layout_marginStart="56dp" tools:text="@string/send_available_btc" /> + android:src="@drawable/ic_sideshift_circle" /> + android:visibility="visible"> + card_view:drawableStartCompat="@drawable/ic_sideshift_circle" /> + android:src="@drawable/ic_monero" /> @@ -128,6 +128,13 @@ android:layout_height="wrap_content" android:layout_centerInParent="true"> + + @@ -151,15 +158,6 @@ android:layout_height="72dp" android:layout_gravity="center" android:visibility="invisible" /> - - - @@ -20,10 +19,10 @@ + android:src="@drawable/ic_monero" /> + android:text="@string/tx_amount" /> + android:text="@string/tx_destination" /> Ledger habilitat, premi aquí per més informació. Heu introduït una adreça de Bitcoin.
- Està a punt d\'enviar XMR i el destinatari rebrà BTC a través del servei SideShift.ai service. + Heu introduït una adreça %1$s.
+ Està a punt d\'enviar XMR i el destinatari rebrà %1$s a través del servei SideShift.ai service. ]]>
Ordre SideShift.ai - %1$s BTC + %1$s %2$s Confirmació Pendent Pagament Pendent Error de SideShift.ai (%1$s) - BTC Enviats! + %1$s Enviats! Consultant … You can send %1$s — %2$s BTC.
- SideShift.ai està oferint una tasa de canvi de %3$s BTC en aquest moment. - ]]>
- Quantitats fins a %1$s BTC seran enviats a l\'instant! + You can send %1$s — %2$s %4$s.
+ SideShift.ai està oferint una tasa de canvi de %3$s %4$s/XMR en aquest moment. ]]>
- Balanç: %2$s BTC (%1$s XMR) + Balanç: %2$s %3$s (%1$s XMR) ✔ ID de pagment integrat Preparant la seva transacció @@ -75,13 +72,13 @@ Vatua l\'olla! Sembla ser que estem encallats! Ups, sembla que SideShift.ai no està disponible ara mateix! - %1$s BTC = %2$s XMR - (Canvi: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Canvi: %1$s %2$s/XMR) Visita SideShift.ai per suport i seguiment Clau secreta\nSideShift.ai Clau secreta SideShift.ai - Adreça BTC de destí + Adreça %1$s de destí Quantitat ID de transacció @@ -251,11 +248,9 @@ ID de transacció Clau de transacció Destí - Destí\n(BTC) ID de pagament Bloc Quantitat - Quantitat\n(BTC) Comissió Transferències Notes @@ -354,11 +349,6 @@ Receptor - SideShift.ai fora de línia - intenti-ho més tard - Quantitat de BTC fora dels límits - URL de pagament no vàlida o obsoleta - Massa peticions - TOT! Convertir la llavor del Ledger @@ -381,8 +371,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -406,4 +396,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b73a845493..94d5ee5f2b 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -35,30 +35,26 @@ Ledger aktiviert – Tippe für mehr Infos. Du hast eine BTC-Adresse eingegeben.
- Du wirst XMR versenden und der Empfänger durch den SideShift.ai Service BTC erhalten. + Du hast eine %1$s-Adresse eingegeben.
+ Du wirst XMR versenden und der Empfänger durch den SideShift.ai Service %1$s erhalten. ]]>
SideShift.ai-Auftrag - %1$s BTC - + %1$s %2$s Bestätigung ausstehend Bezahlung ausstehend SideShift.ai-Fehler (%1$s) - BTC gesendet! + %1$s gesendet! Frage ab … Du kannst %1$s — %2$s BTC senden.
- SideShift.ai gibt dir aktuell einen Wechselkurs von %3$s BTC. - ]]>
- Beträge bis zu %1$s BTC werden sofort versendet! + Du kannst %1$s — %2$s %4$s senden.
+ SideShift.ai gibt dir aktuell einen Wechselkurs von %3$s %4$s/XMR. ]]>
- Guthaben: %2$s BTC (%1$s XMR) + Guthaben: %2$s %3$s (%1$s XMR) ✔ Zahlungs-ID integriert Bereite deine Transaktion vor @@ -76,13 +72,13 @@ Jetzt hängen wir hier fest! Oh oh – SideShift.ai scheint im Moment nicht verfügbar zu sein! - %1$s BTC = %2$s XMR - (Kurs: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Kurs: %1$s %2$s/XMR) Besuche SideShift.ai für Support & Nachverfolgung Geheimer Schlüssel\nSideShift.ai SideShift.ai – Geheimer Schlüssel - BTC-Zieladresse + %1$s-Zieladresse Betrag Transaktions-ID @@ -246,11 +242,9 @@ Transaktions-ID Transaktionsschlüssel Ziel - Ziel\n(BTC) Zahlungs-ID Block Betrag - Betrag\n(BTC) Gebühr Transfers Notizen @@ -357,11 +351,6 @@ Empfänger - SideShift.ai nicht erreichbar – versuche es später nochmal - BTC-Betrag außerhalb des gültigen Bereiches - Ungültige oder veraltete Zahlungs-URL - Zu viele Anfragen - ALLES! Konvertiere Ledger-Seed @@ -384,8 +373,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -409,4 +398,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 675f84158e..f2c4815a0e 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -34,29 +34,26 @@ Ledger ενεργοποιήθηκε, πάτα για περισσότερες πληροφορείες. Έβαλες μια διεύθυνση bitcoin.
- Θα στείλεις XMR και ο παραλήπτης θα πάρει BTC μέσο της υπηρεσίας SideShift.ai. + Έβαλες μια διεύθυνση %1$s.
+ Θα στείλεις XMR και ο παραλήπτης θα πάρει %1$s μέσο της υπηρεσίας SideShift.ai. ]]>
Εντολή SideShift.ai - %1$s BTC + %1$s %2$s Επιβεβαίωση Εκκρεμεί Πληρωμή σε εκκρεμότητα SideShift.ai Σφάλμα (%1$s) - BTC Αποστάλθηκαν! + %1$s Αποστάλθηκαν! Αίτηση … Μπορείς να στείλεις %1$s — %2$s BTC.
- Το SideShift.ai σου δίνει ισοτιμία ανταλλαγής %3$s BTC αυτή τη στιγμή. - ]]>
- Ποσά μέχρι %1$s BTC θα σταλούν άμεσα! + Μπορείς να στείλεις %1$s — %2$s %4$s.
+ Το SideShift.ai σου δίνει ισοτιμία ανταλλαγής %3$s %4$s/XMR αυτή τη στιγμή. ]]>
- Σύνολο: %2$s BTC (%1$s XMR) + Σύνολο: %2$s %3$s (%1$s XMR) ✔ ID πληρωμής ενσωματωμένο Προετοιμασία της συναλλαγής σου @@ -74,13 +71,13 @@ Τώρα έχουμε κολλήσει εδώ! Ωχ,το SideShift.ai φαίνεται να μην ειναι προσωρινά διαθέσιμο! - %1$s BTC = %2$s XMR - (Rate: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Rate: %1$s %2$s/XMR) Επίσκεψη στο SideShift.ai για υποστήριξη & με εντοπισμό συναλλαγής Μυστικό Κλειδί\nSideShift.ai SideShift.ai Μυστικό Κλειδί - BTC Διεύθυνση Παραλήπτη + %1$s Διεύθυνση Παραλήπτη Ποσό ID Συναλλαγής @@ -220,11 +217,9 @@ ID Συναλλαγής(TX ID) Κλειδί συναλλαγής(TX Key) Προορισμός - Προορισμός\n(BTC) ID Πληρωμής(Payment ID) Μπλοκ Ποσό - Ποσό\n(BTC) Κόμιστρο Συναλλαγές Σημειώσεις @@ -356,11 +351,6 @@ Receiver - SideShift.ai offline - try again later - BTC amount out of bounds - Invalid or outdated Payment URL - Too many requests - EVERYTHING! Convert Ledger Seed @@ -383,8 +373,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -408,4 +398,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 6bafaf0236..a112287c60 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -35,29 +35,26 @@ Ledger permesita, frapetu por detaloj. Vi entajpis Bitmono-adreson.
- Vi sendos XMR-on, kaj per laSideShift.ai-servo, la ricevanto havos BTC-on. + Vi entajpis %1$s-adreson.
+ Vi sendos XMR-on, kaj per laSideShift.ai-servo, la ricevanto havos %1$s-on. ]]>
mendo al SideShift.ai - %1$s BTC + %1$s %2$s Konfirmo okazonta Pago okazonta SideShift.ai eraro (%1$s) - BTC sendiĝis! + %1$s sendiĝis! Informpetante … Vi povas sendi %1$s — %2$s BTC.
- SideShift.ai proponas al vi tiun kurzon: %3$s BTC nun. - ]]>
- Kvantoj ĝis %1$s BTC sendiĝos senatende! + Vi povas sendi %1$s — %2$s %4$s.
+ SideShift.ai proponas al vi tiun kurzon: %3$s %4$s/XMR nun. ]]>
- Saldo: %2$s BTC (%1$s XMR) + Saldo: %2$s %3$s (%1$s XMR) ✔ Paga-ID integriĝis Preparante vian transakcion @@ -75,13 +72,13 @@ Ni blokiĝis ĉi tie! Uh-oh, ŝajne SideShift.ai ne disponas momente! - %1$s BTC = %2$s XMR - (kurzo: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (kurzo: %1$s %2$s/XMR) Vizitu SideShift.ai por helpo kaj sekvado Sekreta ŝlosilo\nSideShift.ai SideShift.ai sekreta ŝlosilo - Ricevanta BTC-adreso + Ricevanta %1$s-adreso Kvanto Transakcia ID @@ -251,11 +248,9 @@ TX ID TX Ŝlosilo Destino - Destino\n(BTC) Paga-ID Bloko Kvanto - Kvanto\n(BTC) Kosto Transigoj Notoj @@ -356,11 +351,6 @@ Ricevanto - SideShift.ai ne enretas - provu pli poste - BTC-kvanto tro grandas - La paga URL malvalidas aŭ ne ĝisdatiĝis - Tro da mendoj - ĈIO! Convert Ledger Seed @@ -383,8 +373,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -408,4 +398,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 2b84f3d4de..99974d0a2d 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -218,23 +218,20 @@ Restaurar monedero con claves privadas Restaurar monedero con semilla de 25 palabras Ingresaste una dirección Bitcoin
- Vas a enviar XMR y el destinatario recibirá BTC usando el servicio SideShift.ai. + Ingresaste una dirección %1$s
+ Vas a enviar XMR y el destinatario recibirá %1$s usando el servicio SideShift.ai. ]]>
- %1$s BTC + %1$s %2$s Confirmación pendiente Pago pendiente Error de SideShift.ai (%1$s) - BTC Enviados! + %1$s Enviados! Consultando … Puedes enviar %1$s — %2$s BTC.
- SideShift.ai está ofreciendo una tasa de cambio de %3$s BTC en este momento. + Puedes enviar %1$s — %2$s %4$s.
+ SideShift.ai está ofreciendo una tasa de cambio de %3$s %4$s/XMR en este momento. ]]>
- Montos hasta %1$s BTC serán enviados en el momento! - ]]> - Saldo: %2$s BTC (%1$s XMR) + Saldo: %2$s %3$s (%1$s XMR) Creando orden SideShift.ai Consultando orden SideShift.ai Preparando transacción Monero @@ -244,12 +241,12 @@ Toca para reintentar Parece que estamos atascados! Oh-oh, parece que SideShift.ai no está disponible ahora! - %1$s BTC = %2$s XMR - (Cambio: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Cambio: %1$s %2$s/XMR) Visita https://sideshift.ai para soporte y rastreo Clave secreta\nSideShift.ai Clave secreta SideShift.ai - Dirección BTC destino + Dirección %1$s destino Monto Oye, esperaste demasiado! Clave @@ -261,8 +258,6 @@ Total (XMR) %1$s XMR +%1$s Comisión - Destino\n(BTC) - Monto\n(BTC) Soy monerujo Orden SideShift.ai @@ -347,11 +342,6 @@ Receptor - SideShift.ai offline - try again later - BTC amount out of bounds - Invalid or outdated Payment URL - Too many requests - EVERYTHING! Convert Ledger Seed @@ -374,8 +364,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -399,4 +389,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 8b10e14e49..ad8e6cc16b 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -35,29 +35,26 @@ Ledger\'i tugi sisse lülitatud, puuduta lisainfo saamiseks. Sa sisestasid Bitcoini aadressi.
- See tähendab, et sa saadad Monerosid ning kohale jõuavad Bitcoinid kasutades SideShift.ai teenust. + Sa sisestasid %1$s aadressi.
+ See tähendab, et sa saadad Monerosid ning kohale jõuavad %1$s kasutades SideShift.ai teenust. ]]>
SideShift.ai tellimus - %1$s BTC + %1$s %2$s Ootan kinnitust Ootan makset SideShift.ai viga (%1$s) - BTC saadetud! + %1$s saadetud! Küsin … Sa saad saata %1$s — %2$s BTC.
- SideShift.ai annab hetkel vahetuskursiks %3$s BTC. - ]]>
- Kuni %1$s BTC saadetakse viivitamatult! + Sa saad saata %1$s — %2$s %4$s.
+ SideShift.ai annab hetkel vahetuskursiks %3$s %4$s/XMR. ]]>
- Kontojääk: %2$s BTC (%1$s XMR) + Kontojääk: %2$s %3$s (%1$s XMR) ✔ Makse ID integreeritud Valmistan ülekannet ette @@ -75,13 +72,13 @@ Nüüd jõudsime küll tupikusse! Oh ei, SideShift.ai ei ole hetkel saadaval! - %1$s BTC = %2$s XMR - (Kurss: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Kurss: %1$s %2$s/XMR) Külasta SideShift.ai lisainfo saamiseks & jälgin Privaatvõti\nSideShift.ai SideShift.ai privaatvõti - Sihtkoha Bitcoini aadress + Sihtkoha %1$s aadress Kogus Ülekande ID @@ -246,11 +243,9 @@ Ülekande ID Ülekande võti Sihtkoht - Sihtkoht\n(BTC) Makse ID Plokk Kogus - Kogus\n(BTC) Teenustasu Ülekanded Kommentaarid @@ -354,11 +349,6 @@ Saaja - SideShift.ai offline - try again later - BTC amount out of bounds - Invalid or outdated Payment URL - Too many requests - EVERYTHING! Convert Ledger Seed @@ -381,8 +371,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -406,4 +396,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 41f299819b..563431a8d6 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -35,30 +35,27 @@ Ledger activé, tapez pour plus d\'infos. Vous avez entré une adresse Bitcoin.
- Vous envoyez des XMR et le destinataire recevra des BTC via le service SideShift.ai. + Vous avez entré une adresse %1$s.
+ Vous envoyez des XMR et le destinataire recevra des %1$s via le service SideShift.ai. ]]>
Ordres SideShift.ai - %1$s BTC + %1$s %2$s En Attente de Confirmation En Attente de Paiement Erreur SideShift.ai (%1$s) - BTC Envoyé ! + %1$s Envoyé ! Interrogation … Vous pouvez envoyer %1$s — %2$s BTC.
- SideShift.ai vous donne un taux de change de %3$s BTC actuellement. - ]]>
- Les montant n\'excédant pas %1$s BTC seront envoyés immédiatement! + Vous pouvez envoyer %1$s — %2$s %4$s.
+ SideShift.ai vous donne un taux de change de %3$s %4$s/XMR actuellement. ]]>
- Solde : %2$s BTC (%1$s XMR) + Solde : %2$s %3$s (%1$s XMR) ✔ ID de Paiement intégré Préparation de votre transaction @@ -76,13 +73,13 @@ Maintenant on est coincé ici ! Oh-oh, SideShift.ai n\'a pas l\'air disponible pour le moment ! - %1$s BTC = %2$s XMR - (Taux : %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Taux : %1$s %2$s/XMR) Visitez SideShift.ai pour l\'assistance & le suivi Clef Secrète\nSideShift.ai Clef Secrète SideShift.ai - Adresse BTC Destination + Adresse %1$s Destination Montant ID de Transaction @@ -248,11 +245,9 @@ ID TX Clef TX Destination - Destination\n(BTC) ID de Paiement Bloc Montant - Montant\n(BTC) Frais Transferts Notes @@ -360,11 +355,6 @@ Destinataire - SideShift.ai hors ligne - réessayer ultérieurement - Montant BTC hors limites - URL de Paiement invalide ou périmée - Trop de requêtes - TOTALITÉ! Convertir mnémonique Ledger @@ -387,8 +377,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -412,4 +402,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 5892dde8a9..429404b9e8 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -35,29 +35,26 @@ Ledger engedélyezve, koppints ide a részletekért Bitcoin-címet adtál meg.
- XMR-t fogsz küldeni, a fogadó pedig BTC-t fog kapni az SideShift.ai szolgáltatásán keresztül. + %1$s-címet adtál meg.
+ XMR-t fogsz küldeni, a fogadó pedig %1$s-t fog kapni az SideShift.ai szolgáltatásán keresztül. ]]>
SideShift.ai megrendelés - %1$s BTC + %1$s %2$s Megerősítés folyamatban Kifizetés folyamatban SideShift.ai-hiba (%1$s) - BTC elküldve! + %1$s elküldve! Lekérdezés… Elküldhetsz: %1$s — %2$s BTC.
- Az SideShift.ai aktuális árfolyama: %3$s BTC. - ]]>
- A legfeljebb %1$s BTC nagyságú összegek azonnal elküldésre kerülnek! + Elküldhetsz: %1$s — %2$s %4$s.
+ Az SideShift.ai aktuális árfolyama: %3$s %4$s/XMR. ]]>
- Egyenleg: %2$s BTC (%1$s XMR) + Egyenleg: %2$s %3$s (%1$s XMR) ✔ Fizetési azonosító integrálva Tranzakció előkészítése @@ -75,13 +72,13 @@ Itt most elakadtunk! Ajjaj! Úgy néz ki, az SideShift.ai most nem elérhető! - %1$s BTC = %2$s XMR - (Arány: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Arány: %1$s %2$s/XMR) Segítségért és nyomonkövetésért látogass el az SideShift.ai weboldalra Titkos kulcs\nSideShift.ai SideShift.ai titkos kulcs - Kedvezményezett BTC-címe + Kedvezményezett %1$s-címe Mennyiség Tranzakcióazonosító @@ -245,11 +242,9 @@ Tranzakcióazonosító Tranzkaciós kulcs Cél - Cél\n(BTC) Fizetési azonosító Blokk Mennyiség - Mennyiség\n(BTC) Díj Transzferek Közlemény @@ -358,11 +353,6 @@ Receiver - SideShift.ai offline - try again later - BTC amount out of bounds - Invalid or outdated Payment URL - Too many requests - EVERYTHING! Convert Ledger Seed @@ -385,8 +375,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -410,4 +400,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index b79b50035c..92d9060b58 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -35,30 +35,27 @@ Ledger abilitato, tocca per maggiori informazioni. Hai inserito un indirizzo Bitcoin.
- Invierai XMR e il destinatario riceverà BTC tramite il servizio SideShift.ai. + Hai inserito un indirizzo %1$s.
+ Invierai XMR e il destinatario riceverà %1$s tramite il servizio SideShift.ai. ]]>
Ordine SideShift.ai - %1$s BTC + %1$s %2$s In attesa di conferma In attesa del pagamento Errore SideShift.ai (%1$s) - BTC Inviati! + %1$s Inviati! Richiedendo … Puoi inviare %1$s — %2$s BTC.
- SideShift.ai ti sta attualmente concedendo un tasso di cambio di %3$s BTC. - ]]>
- Ammontare fino a %1$s BTC inviati istantaneamente! + Puoi inviare %1$s — %2$s %4$s.
+ SideShift.ai ti sta attualmente concedendo un tasso di cambio di %3$s %4$s/XMR. ]]>
- Saldo: %2$s BTC (%1$s XMR) + Saldo: %2$s %3$s (%1$s XMR) ✔ ID pagamento integrato Preparando la tua transazione @@ -76,13 +73,13 @@ Ora siamo bloccati qui!! Oh Oh, SideShift.ai sembra non essere disponibile in questo momento! - %1$s BTC = %2$s XMR - (Tasso: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Tasso: %1$s %2$s/XMR) Visita SideShift.ai per supporto e tracciamento Chiave segreta\nSideShift.ai Chiave segreta SideShift.ai - Indirizzo BTC di destinazione + Indirizzo %1$s di destinazione Ammontare ID Transazione @@ -247,11 +244,9 @@ ID TX Chiave TX Destinazione - Destinazione\n(BTC) ID Pagamento Blocco Ammontare - Ammontare\n(BTC) Commissione Trasferimenti Note @@ -359,11 +354,6 @@ Ricevente - SideShift.ai è offline - prova più tardi - Ammontare in BTC fuori dai limiti - URL di pagamento obsoleto o invalido - Troppe richieste - TUTTO! Converti seed Ledger @@ -386,8 +376,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -411,4 +401,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index c40f150519..fec82efe1a 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -35,29 +35,26 @@ レッジャーは有効化されています。詳細はタップしてください。 あなたが入力したのはビットコインのアドレスです。
- あなたはXMRを送金し、受け手は SideShift.ai のサービスを利用してBTCを受取ります。 + あなたが入力したのは%1$sのアドレスです。
+ あなたはXMRを送金し、受け手は SideShift.ai のサービスを利用して%1$sを受取ります。 ]]>
SideShift.ai の注文 - %1$s BTC + %1$s %2$s 承認を待っています 支払いを待っています SideShift.ai のエラー (%1$s) - BTCが送金されました! + %1$sが送金されました! 問い合わせ中 … %1$s から %2$s BTC を送金することができます。
- SideShift.ai での交換レートは現在%3$s BTCです。 - ]]>
- %1$s BTC までの数量は 即時に送金可能です! + %1$s から %2$s %4$s を送金することができます。
+ SideShift.ai での交換レートは現在%3$s %4$s/XMRです。 ]]>
- 残高: %2$s BTC (%1$s XMR) + 残高: %2$s %3$s (%1$s XMR) ✔ ペイメントID組み込み済み 取引を準備しています @@ -75,13 +72,13 @@ 私達はここで立ち往生のようです! あーあ、 SideShift.ai は現在利用不能のようです! - %1$s BTC = %2$s XMR - (レート: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (レート: %1$s %2$s/XMR) サポートと追跡については SideShift.ai をご覧ください シークレットキー\nSideShift.ai SideShift.ai のシークレットキー - 支払先の BTC アドレス + 支払先の %1$s アドレス 数量 取引ID @@ -251,11 +248,9 @@ 取引ID 取引キー 送金先 - 送金先\n(BTC) ペイメントID ブロック 数量 - 数量\n(BTC) 手数料 送金 メモ @@ -359,11 +354,6 @@ 受け取り手 - SideShift.aiはオフラインです。もう一度お試しください - BTCの金額は範囲外 - ペイメントURLは不正古いです - リクエストは多すぎます - 残高合計! Ledgerシードを転換 @@ -386,8 +376,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -411,4 +401,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 73deac15db..bc9ba4188f 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -35,28 +35,25 @@ Ledger tilgjengelig, trykk for mer info. Du skrev inn en Bitcoin addresse.
- Du vil sende XMR og mottakeren vil få BTC gjennom SideShift.ai tjenesten. + Du skrev inn en %1$s addresse.
+ Du vil sende XMR og mottakeren vil få %1$s gjennom SideShift.ai tjenesten. ]]>
SideShift.ai Ordre - %1$s BTC + %1$s %2$s Bekreftelse venter Betaling venter SideShift.ai error (%1$s) - BTC sendt! + %1$s sendt! Spør … Du kan sende %1$s — %2$s BTC.
- SideShift.ai gir deg en vekslingskurs på %3$s BTC akkurat nå. - ]]>
- Mengder opp til %1$s BTC vil bli sendt umiddelbart! + Du kan sende %1$s — %2$s %4$s.
+ SideShift.ai gir deg en vekslingskurs på %3$s %4$s/XMR akkurat nå. ]]>
- Saldo: %2$s BTC (%1$s XMR) + Saldo: %2$s %3$s (%1$s XMR) ✔ Betalings ID integrert Forbereder din transaksjon @@ -74,13 +71,13 @@ Nå sitter vi fast her! Ops, det ser ikke ut til at SideShift.ai er tilgjengelig for øyeblikket! - %1$s BTC = %2$s XMR - (Rate: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Rate: %1$s %2$s/XMR) Besøk SideShift.ai for støtte og sporing Hemmelig nøkkel\nSideShift.ai SideShift.ai Hemmelig nøkkel - BTC destinasjonsadresse + %1$s destinasjonsadresse Mengde Transaksjons-ID @@ -245,11 +242,9 @@ TX ID TX-nøkkel Destinasjon - Destinasjon\n(BTC) Betalings-ID Blokk Mengde - Mengde\n(BTC) Avgift Overføringer Notater @@ -356,11 +351,6 @@ Receiver - SideShift.ai offline - try again later - BTC amount out of bounds - Invalid or outdated Payment URL - Too many requests - EVERYTHING! Convert Ledger Seed @@ -383,8 +373,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -408,4 +398,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b44da6cf47..b903a592c4 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -35,29 +35,26 @@ Ledger ingeschakeld. Tik voor meer info. Je hebt een Bitcoin-adres ingevoerd.
- Je verzendt XMR en de ontvanger krijgt BTC via SideShift.ai. + Je hebt een %1$s-adres ingevoerd.
+ Je verzendt XMR en de ontvanger krijgt %1$s via SideShift.ai. ]]>
SideShift.ai-opdracht - %1$s BTC + %1$s %2$s Wacht op bevestiging Wacht op betaling Fout bij SideShift.ai (%1$s) - BTC verzonden! + %1$s verzonden! Aanvragen… Je kunt %1$s — %2$s BTC verzenden.
- SideShift.ai biedt nu een wisselkoers van %3$s BTC aan. - ]]>
- Bedragen tot %1$s BTC worden meteen verzonden! + Je kunt %1$s — %2$s %4$s verzenden.
+ SideShift.ai biedt nu een wisselkoers van %3$s %4$s/XMR aan. ]]>
- Saldo: %2$s BTC (%1$s XMR) + Saldo: %2$s %3$s (%1$s XMR) ✔ Betalings-ID geïntegreerd Transactie wordt voorbereid @@ -75,13 +72,13 @@ Nu zitten we vast… Oeps, SideShift.ai is op dit moment niet beschikbaar. - %1$s BTC = %2$s XMR - (Koers: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Koers: %1$s %2$s/XMR) Ga naar SideShift.ai voor hulp en traceren Geheime sleutel\nSideShift.ai Geheime sleutel SideShift.ai - BTC-doeladres + %1$s-doeladres Bedrag Transactie-ID @@ -242,11 +239,9 @@ Transactie-ID Transactiesleutel Bestemming - Bestemming\nBTC Betalings-ID Blok Bedrag - Bedrag\nBTC Vergoeding Betalingen Opmerkingen @@ -356,11 +351,6 @@ Ontvanger - SideShift.ai offline - try again later - BTC amount out of bounds - Invalid or outdated Payment URL - Too many requests - EVERYTHING! Convert Ledger Seed @@ -383,8 +373,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -408,4 +398,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index cd7f720012..7e42d762ff 100755 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -35,29 +35,26 @@ Ledger ativada, toque para mais informações. Você colocou um endereço Bitcoin.
- Você enviará XMR e o destinatário receberá BTC via o serviço SideShift.ai + Você colocou um endereço %1$s.
+ Você enviará XMR e o destinatário receberá %1$s via o serviço SideShift.ai ]]>
Ordem no SideShift.ai - %1$s BTC + %1$s %2$s Confirmação Pendente Pagamento Pendente Erro SideShift.ai (%1$s) - BTC Enviado! + %1$s Enviado! Consultando … Você pode enviar %1$s — %2$s BTC.
- SideShift.ai enviou a cotação de %3$s BTC neste momento. - ]]>
- Quantias até %1$s BTC serão enviadas instantaneamente! + Você pode enviar %1$s — %2$s %4$s.
+ SideShift.ai enviou a cotação de %3$s %4$s/XMR neste momento. ]]>
- Saldo: %2$s BTC (%1$s XMR) + Saldo: %2$s %3$s (%1$s XMR) ✔ ID do pagamento integrado Preparando sua transação @@ -75,13 +72,13 @@ Opa, estamos travados aqui! Hm, parece que o SideShift.ai não está disponível no momento - %1$s BTC = %2$s XMR - (Cotação: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Cotação: %1$s %2$s/XMR) Visite o SideShift.ai para suporte & rastreio da ordem Chave secreta\nSideShift.ai Chave secreta SideShift.ai - Endereço BTC de destino + Endereço %1$s de destino Valor ID da Transação @@ -244,11 +241,9 @@ ID TX Chave TX Destino - Destino\n(BTC) ID do Pagamento Bloco Valor - Valor\n(BTC) Taxa Transferências Notas @@ -348,11 +343,6 @@ Destinatário - SideShift.ai offline - tente novamente mais tarde - Valor BTC fora dos limites - URL de pagamento inválido - Solicitações em excesso - TUDO! Converter semente da Ledger @@ -375,8 +365,8 @@ Esse aplicativo permite que você crie e use carteiras Monero. Você poderá guardar seus queridos moneroj aqui. Mantenha sua semente em segurança A semente dá acesso total a qualquer pessoa que a tenha. Se você perdê-la, nós não conseguiremos lhe ajudar a recuperá-la e você perderá seus amados moneroj. - Enviar Bitcoin - A Monerujo possui o SideShift.ai integrado. Basta colar ou escaner um endereço Bitcoin e você estará enviando BTC, mas gastando em XMR. + Enviar Crypto + A Monerujo possui o SideShift.ai integrado. Basta colar ou escaner um endereço BTC, LTC, ETH, DASH ou DOGE e você estará enviando cripto, mas gastando em XMR. "Nós", do seu jeito Os nós conectam você à rede Monero. Escolha entre nós públicos ou seja completamente "cypherpunk" e utilize seu próprio nó. Enviar usando a digital @@ -400,4 +390,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 9b6fea95a8..b6cc1d4220 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -35,29 +35,26 @@ Ledger activa, toca para mais informação. Introduziu um endereço Bitcoin.
- Vai enviar em XMR e o destinatário vai receber BTC através do serviço SideShift.ai + Introduziu um endereço %1$s.
+ Vai enviar em XMR e o destinatário vai receber %1$s através do serviço SideShift.ai ]]>
SideShift.ai Order - %1$s BTC + %1$s %2$s Confirmação Pendente Pagamento Pendente Erro SideShift.ai (%1$s) - BTC Enviadas! + %1$s Enviadas! A comunicar … Pode enviar %1$s — %2$s BTC.
- SideShift.ai está com uma taxa de conversão de %3$s BTC neste momento. - ]]>
- Quantidades até %1$s BTC serão enviadas instantaneament! + Pode enviar %1$s — %2$s %4$s.
+ SideShift.ai está com uma taxa de conversão de %3$s %4$s/XMR neste momento. ]]>
- Saldo: %2$s BTC (%1$s XMR) + Saldo: %2$s %3$s (%1$s XMR) ✔ ID do pagamento integrado A preparar a transacção @@ -75,13 +72,13 @@ Agora estamos emperrados aqui! Ups, SideShift.ai não parece estar disponível neste momento! - %1$s BTC = %2$s XMR - (Rácio: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Rácio: %1$s %2$s/XMR) Vai a SideShift.ai para suporte & seguimento Chave secreta\nSideShift.ai SideShift.ai Chave secreta - Endereço BTC de destino + Endereço %1$s de destino Quantidade ID da Transacção @@ -244,11 +241,9 @@ ID TX Chave TX Destino - Destino\n(BTC) ID Pagamento Bloco Quantidade - Quantidade\n(BTC) Taxa Transferências Notas @@ -360,11 +355,6 @@ Receptor - SideShift.ai offline - tenta mais tarde - Montante de BTC fora dos limites - URL de pagamento invalido ou fora de prazo - Demasiadas solicitações - A TOTALIDADE! Converter semente do Ledger @@ -387,8 +377,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -412,4 +402,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 6a37db66f9..5d2861cb20 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -34,29 +34,26 @@ Ledger activată, apasă pentru mai multe informații. Ai introdus o adresă de Bitcoin.
- Vei trimite XMR și destinatarul va primi BTC folosind serviciul SideShift.ai. + Ai introdus o adresă de %1$s.
+ Vei trimite XMR și destinatarul va primi %1$s folosind serviciul SideShift.ai. ]]>
Ordin SideShift.ai - %1$s BTC + %1$s %2$s Confirmare în așteptare Plată în așteptare Eroare SideShift.ai (%1$s) - BTC trimis! + %1$s trimis! Interogare … Poți trimite %1$s — %2$s BTC.
- SideShift.ai îți oferă un curs de %3$s BTC în acest moment. - ]]>
- Sume până la %1$s BTC vor fi trimise instantaneu! + Poți trimite %1$s — %2$s %4$s.
+ SideShift.ai îți oferă un curs de %3$s %4$s/XMR în acest moment. ]]>
- Balanță: %2$s BTC (%1$s XMR) + Balanță: %2$s %3$s (%1$s XMR) ✔ Payment ID integrat Se pregătește tranzacția @@ -74,13 +71,13 @@ Pff.. ne-am blocat cum! Oh, serviciul SideShift.ai este momentan indisponibil! - %1$s BTC = %2$s XMR - (Rată: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Rată: %1$s %2$s/XMR) Vizitează SideShift.ai pentru suport & interogare Cheia secretă \nSideShift.ai Cheia secretă SideShift.ai - Destinație adresă BTC + Destinație adresă %1$s Sumă ID Tranzacție @@ -220,11 +217,9 @@ ID Tranzacție Cheie tranzacție Destinație - Destinație\n(BTC) Payment ID Monobloc Sumă - Sumă\n(BTC) Comision Transferuri Notițe @@ -356,11 +351,6 @@ Receiver - SideShift.ai offline - try again later - BTC amount out of bounds - Invalid or outdated Payment URL - Too many requests - EVERYTHING! Convert Ledger Seed @@ -383,8 +373,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -408,4 +398,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a04c2157bf..0d97e893eb 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -35,30 +35,27 @@ Доступен Ledger, нажмите для доп. информации Вы ввели Bitcoin адрес.
- Отправляйте XMR, получатель получит BTC, используя сервис SideShift.ai + Вы ввели %1$s адрес.
+ Отправляйте XMR, получатель получит %1$s, используя сервис SideShift.ai ]]>
Заказ SideShift.ai - %1$s BTC + %1$s %2$s Ожидание подтверждения Ожидание платежа Ошибка SideShift.ai (%1$s) - BTC успешно отправлены! + %1$s успешно отправлены! Запрос … Вы можете отправить %1$s — %2$s BTC.
- SideShift.ai устанавливает курс обмена %3$s BTC в данный момент. - ]]>
- Сумма до %1$s BTC будет отправлена немедленно! + Вы можете отправить %1$s — %2$s %4$s.
+ SideShift.ai устанавливает курс обмена %3$s %4$s/XMR в данный момент. ]]>
- Баланс: %2$s BTC (%1$s XMR) + Баланс: %2$s %3$s (%1$s XMR) ✔ Интегрированный ID платежа Подготовка транзакции @@ -76,13 +73,13 @@ Теперь мы застряли здесь! Ой-ой! Кажется SideShift.ai недоступен в данный момент! - %1$s BTC = %2$s XMR - (Курс: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Курс: %1$s %2$s/XMR) Посетите SideShift.ai для получения помощи & Секретный ключ\nSideShift.ai SideShift.ai секретный ключ - Адрес получателя BTC + Адрес получателя %1$s Сумма ID транзакции @@ -246,11 +243,9 @@ TX ID Ключ TX Адресат - Адресат\n(BTC) ID платежа Блок Сумма - Сумма\n(BTC) Комиссия Переводы Заметки @@ -360,11 +355,6 @@ Получатель - SideShift.ai недоступен - повторите попытку позже - Сумма BTC выходит за доступные пределы - Неверный или устаревший платежный URL - Превышен лимит запросов - ВСЕ! Преобразовать фразу Ledger @@ -387,8 +377,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -412,4 +402,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 1384e297d5..86e720cb1f 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -35,30 +35,27 @@ Ledger aktivovaný, klepni pre viac info. Vložil si Bitcoin adresu.
- Pošleš XMR a adresát dostane BTC cez službu SideShift.ai. + Vložil si %1$s adresu.
+ Pošleš XMR a adresát dostane %1$s cez službu SideShift.ai. ]]>
SideShift.ai Objednávka - %1$s BTC + %1$s %2$s Čaká na Potvrdenie Čakajúca Platba SideShift.ai Chyba (%1$s) - BTC Odoslané! + %1$s Odoslané! Zisťujem … Môžeš poslať %1$s — %2$s BTC.
- SideShift.ai ti dáva výmenný kurz of %3$s BTC práve teraz. - ]]>
- čiastka do %1$s BTC bude odoslaná okamžite! + Môžeš poslať %1$s — %2$s %4$s.
+ SideShift.ai ti dáva výmenný kurz of %3$s %4$s/XMR práve teraz. ]]>
- Zostatok: %2$s BTC (%1$s XMR) + Zostatok: %2$s %3$s (%1$s XMR) ✔ Payment ID integrované Pripravujem transakciu @@ -76,13 +73,13 @@ Uviazli sme tu! Myslím, že služba SideShift.ai nie je momentálne dostupná! - %1$s BTC = %2$s XMR - (Kurz: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Kurz: %1$s %2$s/XMR) Navštív SideShift.ai pre podporu & tracking Tajný kľúč\nSideShift.ai SideShift.ai Tajný kľúč - Cieľová BTC Adresa + Cieľová %1$s Adresa Čiastka ID Transakcie @@ -243,11 +240,9 @@ TX ID Kľúč Transakcie Cieľ - Cieľová (BTC) ID Platby Blok Suma - Čiastka\n(BTC) poplatok Poslaných Poznámky @@ -357,11 +352,6 @@ Príjemca - SideShift.ai je offline - skús neskôr - Množstvo BTC je mimo rámca - Neplatná alebo stará URL platby - Príliš veľa požiadaviek - VŠETKO! Konvertuj Ledger Seed @@ -384,8 +374,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -409,4 +399,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 3a44afdfa2..ad42e37b84 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -35,29 +35,26 @@ Knjiga računa omogućena, tapni za više info. Ubacio/la si Bitkoin adresu.
- You'će poslati XMR a primalac će dobiti BTC koristeći SideShift.ai servis. + Ubacio/la si %1$s adresu.
+ You'će poslati XMR a primalac će dobiti %1$s koristeći SideShift.ai servis. ]]>
SideShift.ai Nalog - %1$s BTC + %1$s %2$s Potvrda u toku Plaćanje u toku SideShift.ai Greška (%1$s) - BTC Poslato! + %1$s Poslato! Ispitivanje … Možeš poslati %1$s — %2$s BTC.
- SideShift.ai daje ti devizni kurs od %3$s BTC trenutno. - ]]>
- Sume do %1$s BTC biće poslate instantly! + Možeš poslati %1$s — %2$s %4$s.
+ SideShift.ai daje ti devizni kurs od %3$s %4$s/XMR trenutno. ]]>
- Stanje: %2$s BTC (%1$s XMR) + Stanje: %2$s %3$s (%1$s XMR) ✔ ID plaćanja integrisan Priprema tvoje transakcije @@ -75,13 +72,13 @@ Sada se zaglavismo! Uh, SideShift.ai izgleda da sad nije dostupan! - %1$s BTC = %2$s XMR - (Rate: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Rate: %1$s %2$s/XMR) Poseti SideShift.ai za bekap & praćenje Tajna šifra\nSideShift.ai SideShift.ai Tajna šifra - Odredište BTC adrese + Odredište %1$s adrese Suma ID transakcije @@ -252,11 +249,9 @@ TX ID TX šifra Odredište - Odredište\n(BTC) ID plaćanja Blok Suma - Suma\n(BTC) Naknada Transferi Čvorovi @@ -355,11 +350,6 @@ Primalac - SideShift.ai van mreže - pokušajte kasnije ponovo - BTC iznos izvan granica - Nevalidan ili neažuriran URL plaćanja - Previše zahteva - SVE! Pretvori seme iz knjige računa @@ -382,8 +372,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -407,4 +397,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index c4680bc5bc..d11cfcbc92 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -34,22 +34,27 @@ BTC-betalning aktiverad, tryck för mer info. Ledger aktiverat, tryck för mer info. - Du har angivit en Bitcoin-adress.
Du kommer att skicka XMR och mottagaren får BTC via tjänsten SideShift.ai.]]>
+ Du har angivit en %1$s-adress.
+ Du kommer att skicka XMR och mottagaren får %1$s via tjänsten SideShift.ai. + ]]>
SideShift.ai-beställning - %1$s BTC + %1$s %2$s Väntar på bekräftelse Väntar på betalning SideShift.ai-fel (%1$s) - BTC skickades! + %1$s skickades! Frågar … - Du kan skicka %1$s — %2$s BTC.
SideShift.ai ger dig just nu en växelkurs på %3$s BTC.]]>
- Belopp upp till %1$s BTC skickas omedelbart!]]> + Du kan skicka %1$s — %2$s %4$s.
+ SideShift.ai ger dig just nu en växelkurs på %3$s %4$s/XMR. + ]]>
- Saldo: %2$s BTC (%1$s XMR) + Saldo: %2$s %3$s (%1$s XMR) ✔ Betalnings-ID integrerat Förbereder din transaktion @@ -67,13 +72,13 @@ Nu har vi kört fast! Åh nej, SideShift.ai verkar inte vara tillgänglig just nu! - %1$s BTC = %2$s XMR - (Kurs: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Kurs: %1$s %2$s/XMR) Besök SideShift.ai för support & spårning Hemlig nyckel\nSideShift.ai SideShift.ai hemlig nyckel - Måladress för BTC + Måladress för %1$s Belopp Transaktions-ID @@ -225,11 +230,9 @@ TX-ID TX-nyckel Mål - Mål\n(BTC) Betalnings-ID Block Belopp - Belopp\n(BTC) Avgift Överföringar Anteckningar @@ -340,11 +343,6 @@ Mottagaren - SideShift.ai offline - try again later - BTC amount out of bounds - Invalid or outdated Payment URL - Too many requests - EVERYTHING! Convert Ledger Seed @@ -367,8 +365,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -392,4 +390,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 2489199e56..bf66f77c32 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -35,30 +35,27 @@ Доступний Ledger, натисніть для доп. інформації Ви ввели Bitcoin адресу.
- Надсилайте XMR, одержувач отримає BTC, використовуючи сервіс SideShift.ai + Ви ввели %1$s адресу.
+ Надсилайте XMR, одержувач отримає %1$s, використовуючи сервіс SideShift.ai ]]>
Заявка SideShift.ai - %1$s BTC + %1$s %2$s Очікування підтвердження Очікування платежу Помилка SideShift.ai (%1$s) - BTC успішно відправлені! + %1$s успішно відправлені! Запит … Ви можете відправити %1$s — %2$s BTC.
- SideShift.ai встановлює курс обміну %3$s BTC в даний момент. - ]]>
- Сума до %1$s BTC буде відправлена негайно! + Ви можете відправити %1$s — %2$s %4$s.
+ SideShift.ai встановлює курс обміну %3$s %4$s/XMR в даний момент. ]]>
- Баланс: %2$s BTC (%1$s XMR) + Баланс: %2$s %3$s (%1$s XMR) ✔ Інтегрований ID платежу Підготовка транзакції @@ -76,13 +73,13 @@ Тепер ми застрягли тут! Ой ой! Здається SideShift.ai недоступний в даний момент! - %1$s BTC = %2$s XMR - (Курс: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Курс: %1$s %2$s/XMR) Відвідайте SideShift.ai для отримання допомоги & Секретний ключ\nSideShift.ai SideShift.ai секретний ключ - Адреса отримувача BTC + Адреса отримувача %1$s Сума ID транзакції @@ -246,11 +243,9 @@ TX ID Ключ TX Адресат - Адресат\n(BTC) ID платежу Блок Сума - Сума\n(BTC) Комісія Перекази Замітки @@ -360,11 +355,6 @@ Отримувач - SideShift.ai недоступний - спробуйте пізніше - Сума BTC виходить за допустимі ліміти - Невірний або застарілий платіжний URL - Перевищено кількість запитів - ВСЕ! Конвертувати фразу Ledger @@ -387,8 +377,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -412,4 +402,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 6021d308ec..622c2a96eb 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -27,24 +27,21 @@ 已支持比特币支付,点此了解更多 已支持Ledger硬件钱包,点此了解更多 您输入了一个比特币地址
-您发送的门罗币将通过SideShift.ai服务,转换为比特币发送给对方。 -]]>
+ 您输入了一个%1$s地址
+ 您发送的门罗币将通过SideShift.ai服务,转换为%1$s发送给对方。 + ]]> SideShift.ai订单 - %1$s BTC + %1$s %2$s 等待确认中 等待支付中 SideShift.ai错误(%1$s) - 成功发送比特币! + 成功发送%1$s! 查询中… 您可以发送%1$s — %2$s BTC.
-此刻SideShift.ai的汇率是%3$s BTC . -]]>
- 至多%1$s BTC将会即刻发送! -]]> - 余额: %2$s BTC (%1$s XMR) + 您可以发送%1$s — %2$s %4$s.
+ 此刻SideShift.ai的汇率是%3$s %4$s/XMR . + ]]> + 余额: %2$s %3$s (%1$s XMR) ✔ 支付ID已集成 正在为您的交易做准备工作 创建SideShift.ai订单 @@ -56,12 +53,12 @@ 再次尝试 我们遇到了困难! 抱歉, SideShift.ai服务现在似乎不可用 - %1$s BTC = %2$s XMR - (Rate: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Rate: %1$s %2$s/XMR) 访问SideShift.ai以获得更多支持 密钥\nSideShift.ai SideShift.ai密钥 - 比特币收款地址 + %1$s收款地址 金额 交易ID 收款地址 @@ -196,11 +193,9 @@ 交易ID 交易密钥 目标地址 - 目标地址\n(BTC) 支付ID 区块 金额 - 金额\n(BTC) 手续费 转账 备注 @@ -281,10 +276,6 @@ 已自动将最佳%1$d节点加入书签 测试 收款人 - SideShift.ai离线-请稍后重试 - 比特币金额超出限制 - 无效或过期的支付URL - 当前请求数过多 全部资产! 转换Ledger种子密语 Ledger种子密语 @@ -306,8 +297,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -331,4 +322,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 98ea2481f1..12d518ab3f 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -35,30 +35,27 @@ Ledger 已啟用,點選了解更多 你輸入了 Bitcoin 地址
- 你將會發送 XMR 而收款方將會收到 BTC (由 SideShift.ai 提供轉換) + 你輸入了 %1$s 地址
+ 你將會發送 XMR 而收款方將會收到 %1$s (由 SideShift.ai 提供轉換) ]]>
SideShift.ai 訂單 - %1$s BTC + %1$s %2$s 等待確認中 等待付款中 SideShift.ai 發生錯誤 (%1$s) - BTC 已發送! + %1$s 已發送! 查詢中 … 你可發送 %1$s — %2$s BTC.
- SideShift.ai 提供的即時匯率為 %3$s BTC. - ]]>
- 金額少於 %1$s BTC ,將會馬上發送! + 你可發送 %1$s — %2$s %4$s.
+ SideShift.ai 提供的即時匯率為 %3$s %4$s/XMR. ]]>
- 餘額:%2$s BTC (%1$s XMR) + 餘額:%2$s %3$s (%1$s XMR) ✔ 已加入付款 ID 正在準備你的交易 @@ -76,13 +73,13 @@ 我們卡住了! 不好,SideShift.ai 現在似乎無法提供服務! - %1$s BTC = %2$s XMR - (匯率:%1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (匯率:%1$s %2$s/XMR) 參訪 SideShift.ai 以獲得支援及追蹤交易 私鑰\nSideShift.ai SideShift.ai 私鑰 - 目的地 BTC 地址 + 目的地 %1$s 地址 金額 交易 ID @@ -244,11 +241,9 @@ 交易 ID (TXID) 交易金鑰 (TX Key) 收款地址 - 收款地址\n(BTC) 付款 ID 區塊 金額 - 金額\n(BTC) 手續費 轉帳 附註 @@ -355,11 +350,6 @@ 收款者 - SideShift.ai 無法使用 - 請稍候再試 - BTC 金額超出限制 - 無效或過期的付款網址 - 請求過於頻繁 - 全部! 轉換 Ledger 種子碼 @@ -382,8 +372,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -407,4 +397,18 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 219f14d43e..6157b4b664 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -32,33 +32,30 @@ Touch for QR Code - BTC payment enabled, tap for more info. + Non-XMR payments enabled, tap for more info. Ledger enabled, tap for more info. You entered a Bitcoin address.
- You'll send XMR and the receiver will get BTC using the SideShift.ai service. + You entered a %1$s address.
+ You'll send XMR and the receiver will get %1$s using the SideShift.ai service. ]]>
SideShift.ai Order - %1$s BTC + %1$s %2$s Confirmation Pending Payment Pending SideShift.ai Error (%1$s) - BTC Sent! + %1$s Sent! Querying … You can send %1$s — %2$s BTC.
- SideShift.ai is giving you an exchange rate of %3$s BTC right now. - ]]>
- Amounts up to %1$s BTC will be sent instantly! + You can send %1$s — %2$s %4$s.
+ SideShift.ai is giving you an exchange rate of %3$s %4$s/XMR right now. ]]>
- Balance: %2$s BTC (%1$s XMR) + Balance: %2$s %3$s (%1$s XMR) ✔ Payment ID integrated Preparing your transaction @@ -76,13 +73,13 @@ Now we\'re stuck here! Uh-oh, SideShift.ai does not seem be available right now! - %1$s BTC = %2$s XMR - (Rate: %1$s BTC/XMR) + %1$s %3$s = %2$s XMR + (Rate: %1$s %2$s/XMR) Visit SideShift.ai for support & tracking Secret Key\nSideShift.ai SideShift.ai Secret Key - Destination BTC Address + Destination %1$s Address Amount Transaction ID @@ -256,11 +253,9 @@ TX ID TX Key Destination - Destination\n(BTC) Payment ID Block Amount - Amount\n(BTC) Fee Transfers Notes @@ -403,13 +398,6 @@ Receiver - SideShift.ai offline - try again later - BTC amount out of bounds - Invalid or outdated Payment URL - Too many requests - - SideShift.ai Service Error - EVERYTHING! Convert Ledger Seed @@ -434,8 +422,8 @@ This app allows you to create and use Monero wallets. You can store your sweet moneroj in them. Keep your seed safe The seed grants full access to whoever has it. If you lose it, we cannot help you recover it and you lose your beloved moneroj. - Send Bitcoin - Monerujo has SideShift.ai support built-in. Just paste or scan a Bitcoin address and you\'ll be sending BTC by spending XMR. + Send Crypto + Monerujo has SideShift.ai support built-in. Just paste or scan a BTC, LTC, ETH, DASH or DOGE address and you\'ll be sending these cryptos by spending XMR. Nodes, your way Nodes connect you to the Monero network. Choose between public nodes or go full cypherpunk using your own. Send with fingerprint @@ -459,4 +447,28 @@ Cannot get quote Check amount and try again + + Ambiguous address.
+ Please select the type above. + ]]>
+ + Please enter or scan a %1$s address.
+ You'll send XMR and the receiver will get %2$s using the SideShift.ai service. + ]]>
+ + Please enter or scan a Monero address. + ]]> + + + + Monero + Bitcoin + Dash + Dogecoin + Ethereum + Litecoin + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 7b58d13757..9359a130e2 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -95,6 +95,11 @@ + + +