diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index b0a67ef..80cee87 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -171,6 +171,10 @@ add_library(wallet-crypto STATIC IMPORTED) set_target_properties(wallet-crypto PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/wownero/libwallet-crypto.a) +add_library(cryptonote_format_utils_basic STATIC IMPORTED) +set_target_properties(cryptonote_format_utils_basic PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/monero/libcryptonote_format_utils_basic.a) + ############# # System ############# @@ -193,6 +197,7 @@ target_link_libraries( monerujo wallet cryptonote_core cryptonote_basic + cryptonote_format_utils_basic mnemonics ringct ringct_basic diff --git a/app/build.gradle b/app/build.gradle index 3c32910..a96b0ca 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,14 +2,14 @@ apply plugin: 'com.android.application' android { compileSdkVersion 30 - buildToolsVersion '30.0.2' + buildToolsVersion '30.0.3' ndkVersion '17.2.4988734' defaultConfig { applicationId "com.m2049r.wowwallet" minSdkVersion 21 targetSdkVersion 30 - versionCode 100500 - versionName "2.0.5.0 'Puginarug'" + versionCode 11010 + versionName "2.1.1.0 'Vertant'" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1ab0d19..0f22430 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ package="com.m2049r.xmrwallet"> + diff --git a/app/src/main/cpp/monerujo.cpp b/app/src/main/cpp/monerujo.cpp index 0e74282..a1144d7 100644 --- a/app/src/main/cpp/monerujo.cpp +++ b/app/src/main/cpp/monerujo.cpp @@ -914,8 +914,8 @@ Java_com_m2049r_xmrwallet_model_Wallet_refreshAsync(JNIEnv *env, jobject instanc //virtual void rescanBlockchainAsync() = 0; JNIEXPORT void JNICALL -Java_com_m2049r_xmrwallet_model_Wallet_rescanBlockchainAsync(JNIEnv *env, jobject instance) { - Monero::Wallet *wallet = getHandle(env, instance); +Java_com_m2049r_xmrwallet_model_Wallet_rescanBlockchainAsyncJ(JNIEnv *env, jobject instance) { + Bitmonero::Wallet *wallet = getHandle(env, instance); wallet->rescanBlockchainAsync(); } diff --git a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java index a35ced4..caff0f0 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java @@ -578,7 +578,6 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste try { final WalletFragment walletFragment = getWalletFragment(); if (wallet.isSynchronized()) { - Timber.d("onRefreshed() synced"); releaseWakeLock(RELEASE_WAKE_LOCK_DELAY); // the idea is to stay awake until synced if (!synced) { // first sync onProgress(-1); diff --git a/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java b/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java index 3bd60ec..35a9398 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java @@ -58,7 +58,6 @@ import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Objects; import timber.log.Timber; @@ -128,7 +127,7 @@ public class WalletFragment extends Fragment currencies.add(Helper.BASE_CRYPTO); if (Helper.SHOW_EXCHANGERATES) currencies.addAll(Arrays.asList(getResources().getStringArray(R.array.currency))); - ArrayAdapter spinnerAdapter = new ArrayAdapter<>(Objects.requireNonNull(getContext()), R.layout.item_spinner_balance, currencies); + ArrayAdapter spinnerAdapter = new ArrayAdapter<>(requireContext(), R.layout.item_spinner_balance, currencies); spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); sCurrency.setAdapter(spinnerAdapter); @@ -346,13 +345,18 @@ public class WalletFragment extends Fragment // if account index has changed scroll to top? private int accountIndex = 0; - public void onRefreshed(final Wallet wallet, final boolean full) { + public void onRefreshed(final Wallet wallet, boolean full) { Timber.d("onRefreshed(%b)", full); + if (adapter.needsTransactionUpdateOnNewBlock()) { + wallet.refreshHistory(); + full = true; + } if (full) { List list = new ArrayList<>(); final long streetHeight = activityCallback.getStreetModeHeight(); Timber.d("StreetHeight=%d", streetHeight); + wallet.refreshHistory(); for (TransactionInfo info : wallet.getHistory().getAll()) { Timber.d("TxHeight=%d, Label=%s", info.blockheight, info.subaddressLabel); if ((info.isPending || (info.blockheight >= streetHeight)) @@ -561,7 +565,7 @@ public class WalletFragment extends Fragment //TODO figure out why gunther disappears on return from send although he is still set if (enable) { if (streetGunther == null) - streetGunther = ContextCompat.getDrawable(Objects.requireNonNull(getContext()), R.drawable.ic_gunther_streetmode); + streetGunther = ContextCompat.getDrawable(requireContext(), R.drawable.ic_gunther_streetmode); ivStreetGunther.setImageDrawable(streetGunther); } else ivStreetGunther.setImageDrawable(null); 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 38feb6a..56a12e3 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 @@ -349,7 +349,7 @@ public class SendAddressWizardFragment extends SendWizardFragment { private boolean checkAddress() { boolean ok = checkAddressNoError(); - if (!ok) { + if (possibleCryptos.isEmpty()) { etAddress.setError(getString(R.string.send_address_invalid)); } else { etAddress.setError(null); 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 0a90c2a..8f1616f 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 @@ -90,7 +90,6 @@ public class SendBtcAmountWizardFragment extends SendWizardFragment { return view; } - @Override public boolean onValidateFields() { Timber.i(maxBtc + "/" + minBtc); 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 b552854..94d2e8e 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 @@ -359,40 +359,22 @@ public class SendBtcConfirmWizardFragment extends SendWizardFragment implements } private RequestQuote xmrtoQuote = null; - private int stageARetries = 0; - private final int RETRIES = 3; - private double stageAPrice = 0; private void processStageA(final RequestQuote requestQuote) { Timber.d("processCreateOrder %s", requestQuote.getId()); TxDataBtc txDataBtc = (TxDataBtc) sendListener.getTxData(); - // verify the BTC amount is correct (price can change and we can only specify XMR amount) + // verify the BTC amount is correct if (requestQuote.getBtcAmount() != txDataBtc.getBtcAmount()) { - if (--stageARetries <= 0) { - Timber.d("Failed to get quote"); - getView().post(() -> - showStageError(ShiftError.Error.SERVICE.toString(), - getString(R.string.shift_noquote), - getString(R.string.shift_checkamount))); - return; // just stop for now - } - if (stageAPrice == requestQuote.getPrice()) { - // same price but different BTC amount - something else is wrong (e.g. too many decimals) - Timber.d("Price unchanged"); - getView().post(() -> - showStageError(ShiftError.Error.SERVICE.toString(), - getString(R.string.shift_noquote), - getString(R.string.shift_checkamount))); - return; // just stop for now - } - stageAPrice = requestQuote.getPrice(); - // recalc XMR and try again - txDataBtc.setAmount(txDataBtc.getBtcAmount() / requestQuote.getPrice()); - getView().post(this::stageAOneShot); - return; // stageA will run in the main thread + Timber.d("Failed to get quote"); + getView().post(() -> showStageError(ShiftError.Error.SERVICE.toString(), + getString(R.string.shift_noquote), + getString(R.string.shift_checkamount))); + return; // just stop for now } xmrtoQuote = requestQuote; + txDataBtc.setAmount(xmrtoQuote.getXmrAmount()); getView().post(() -> { + // show data from the actual quote as that is what is used to NumberFormat df = NumberFormat.getInstance(Locale.US); df.setMaximumFractionDigits(12); final String btcAmount = df.format(xmrtoQuote.getBtcAmount()); @@ -438,18 +420,12 @@ public class SendBtcConfirmWizardFragment extends SendWizardFragment implements } private void stageA() { - stageARetries = RETRIES; - stageAOneShot(); - } - - private void stageAOneShot() { if (!isResumed) return; Timber.d("Request Quote"); xmrtoQuote = null; xmrtoOrder = null; showProgress(1, getString(R.string.label_send_progress_xmrto_create)); TxDataBtc txDataBtc = (TxDataBtc) sendListener.getTxData(); - stageAPrice = 0; ShiftCallback callback = new ShiftCallback() { @Override @@ -473,7 +449,7 @@ public class SendBtcConfirmWizardFragment extends SendWizardFragment implements } }; - getXmrToApi().requestQuote(txDataBtc.getAmountAsDouble(), callback); + getXmrToApi().requestQuote(txDataBtc.getBtcAmount(), callback); } private CreateOrder xmrtoOrder = null; 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 cb21a92..f7c4f93 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java +++ b/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java @@ -30,6 +30,7 @@ import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.progressindicator.CircularProgressIndicator; import com.m2049r.xmrwallet.R; import com.m2049r.xmrwallet.data.Crypto; import com.m2049r.xmrwallet.data.UserNotes; @@ -48,7 +49,7 @@ import java.util.TimeZone; import timber.log.Timber; public class TransactionInfoAdapter extends RecyclerView.Adapter { - private final SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + private final static SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm"); private final int outboundColour; private final int inboundColour; @@ -77,6 +78,10 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter 0) && !infoItems.get(0).isConfirmed(); + } + private static class TransactionInfoDiff extends DiffCallback { public TransactionInfoDiff(List oldList, List newList) { @@ -95,6 +100,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter transactions = new ArrayList<>(); - public void refreshWithNotes(Wallet wallet) { + void refreshWithNotes(Wallet wallet) { refresh(); loadNotes(wallet); } -// public void refresh() { -// transactions = refreshJ(); -// } - - public void refresh() { + private void refresh() { List transactionInfos = refreshJ(); - Timber.d("refreshed %d", transactionInfos.size()); + Timber.d("refresh size=%d", transactionInfos.size()); for (Iterator iterator = transactionInfos.iterator(); iterator.hasNext(); ) { TransactionInfo info = iterator.next(); if (info.accountIndex != accountIndex) { iterator.remove(); - Timber.d("removed %s", info.hash); - } else { - Timber.d("kept %s", info.hash); } } transactions = transactionInfos; } private native List refreshJ(); - } diff --git a/app/src/main/java/com/m2049r/xmrwallet/model/TransactionInfo.java b/app/src/main/java/com/m2049r/xmrwallet/model/TransactionInfo.java index 17af680..4b904e1 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/model/TransactionInfo.java +++ b/app/src/main/java/com/m2049r/xmrwallet/model/TransactionInfo.java @@ -29,6 +29,8 @@ import lombok.RequiredArgsConstructor; // this is not the TransactionInfo from the API as that is owned by the TransactionHistory // this is a POJO for the TransactionInfoAdapter public class TransactionInfo implements Parcelable, Comparable { + public static final int CONFIRMATION = 10; // blocks + @RequiredArgsConstructor public enum Direction { Direction_In(0), @@ -98,6 +100,10 @@ public class TransactionInfo implements Parcelable, Comparable this.transfers = transfers; } + public boolean isConfirmed() { + return confirmations >= CONFIRMATION; + } + public String getDisplayLabel() { if (subaddressLabel.isEmpty() || (Subaddress.DEFAULT_LABEL_FORMATTER.matcher(subaddressLabel).matches())) return ("#" + addressIndex); diff --git a/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java b/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java index 103a50a..47df8e0 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java +++ b/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java @@ -273,12 +273,14 @@ public class Wallet { public native long getDaemonBlockChainTargetHeight(); - public native boolean isSynchronizedJ(); + boolean synced = false; public boolean isSynchronized() { - final long daemonHeight = getDaemonBlockChainHeight(); - if (daemonHeight == 0) return false; - return isSynchronizedJ() && (getBlockChainHeight() == daemonHeight); + return synced; + } + + public void setSynchronized() { + this.synced = true; } public static native String getDisplayAmount(long amount); @@ -309,7 +311,12 @@ public class Wallet { public native void refreshAsync(); - public native void rescanBlockchainAsync(); + public native void rescanBlockchainAsyncJ(); + + public void rescanBlockchainAsync() { + synced = false; + rescanBlockchainAsyncJ(); + } //TODO virtual void setAutoRefreshInterval(int millis) = 0; //TODO virtual int autoRefreshInterval() const = 0; @@ -391,6 +398,10 @@ public class Wallet { private native long getHistoryJ(); + public void refreshHistory() { + getHistory().refreshWithNotes(this); + } + //virtual AddressBook * addressBook() const = 0; //virtual void setListener(WalletListener *) = 0; @@ -455,7 +466,7 @@ public class Wallet { public void setSubaddressLabel(int addressIndex, String label) { setSubaddressLabel(accountIndex, addressIndex, label); - getHistory().refreshWithNotes(this); + refreshHistory(); } public native void setSubaddressLabel(int accountIndex, int addressIndex, String label); diff --git a/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java b/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java index 9598a4b..65bf9ef 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java +++ b/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java @@ -108,23 +108,23 @@ public class WalletService extends Service { Timber.d("unconfirmedMoneyReceived() %d @ %s", amount, txId); } - long lastBlockTime = 0; - int lastTxCount = 0; + private long lastBlockTime = 0; + private int lastTxCount = 0; public void newBlock(long height) { - Wallet wallet = getWallet(); + final Wallet wallet = getWallet(); if (wallet == null) throw new IllegalStateException("No wallet!"); // don't flood with an update for every block ... if (lastBlockTime < System.currentTimeMillis() - 2000) { - Timber.d("newBlock() @ %d with observer %s", height, observer); lastBlockTime = System.currentTimeMillis(); + Timber.d("newBlock() @ %d with observer %s", height, observer); if (observer != null) { boolean fullRefresh = false; updateDaemonState(wallet, wallet.isSynchronized() ? height : 0); if (!wallet.isSynchronized()) { updated = true; // we want to see our transactions as they come in - wallet.getHistory().refresh(); + wallet.refreshHistory(); int txCount = wallet.getHistory().getCount(); if (txCount > lastTxCount) { // update the transaction list only if we have more than before @@ -145,17 +145,16 @@ public class WalletService extends Service { updated = true; } - public void refreshed() { + public void refreshed() { // this means it's synced Timber.d("refreshed()"); - Wallet wallet = getWallet(); + final Wallet wallet = getWallet(); if (wallet == null) throw new IllegalStateException("No wallet!"); + wallet.setSynchronized(); if (updated) { + updateDaemonState(wallet, wallet.getBlockChainHeight()); + wallet.refreshHistory(); if (observer != null) { - updateDaemonState(wallet, 0); - wallet.getHistory().refreshWithNotes(wallet); - if (observer != null) { - updated = !observer.onRefreshed(wallet, true); - } + updated = !observer.onRefreshed(wallet, true); } } } 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 6a1b802..c87465e 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 @@ -74,10 +74,10 @@ class RequestQuoteImpl implements RequestQuote { price = jsonObject.getDouble("rate"); } - public static void call(@NonNull final ShiftApiCall api, final double xmrAmount, + public static void call(@NonNull final ShiftApiCall api, final double btcAmount, @NonNull final ShiftCallback callback) { try { - final JSONObject request = createRequest(xmrAmount); + final JSONObject request = createRequest(btcAmount); api.call("quotes", request, new NetworkCallback() { @Override public void onSuccess(JSONObject jsonObject) { @@ -104,13 +104,13 @@ class RequestQuoteImpl implements RequestQuote { * @param xmrAmount how much XMR to shift to BTC */ - static JSONObject createRequest(final double xmrAmount) throws JSONException { + static JSONObject createRequest(final double btcAmount) throws JSONException { final JSONObject jsonObject = new JSONObject(); jsonObject.put("depositMethod", "xmr"); jsonObject.put("settleMethod", ServiceHelper.ASSET); // #sideshift is silly and likes numbers as strings - String amount = AmountFormatter.format(xmrAmount); - jsonObject.put("depositAmount", amount); + String amount = AmountFormatter.format(btcAmount); + jsonObject.put("settleAmount", amount); return jsonObject; } diff --git a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/SideShiftApiImpl.java b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/SideShiftApiImpl.java index 6cec574..b27ae60 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/SideShiftApiImpl.java +++ b/app/src/main/java/com/m2049r/xmrwallet/service/shift/sideshift/network/SideShiftApiImpl.java @@ -64,8 +64,8 @@ public class SideShiftApiImpl implements SideShiftApi, ShiftApiCall { } @Override - public void requestQuote(final double xmrAmount, @NonNull final ShiftCallback callback) { - RequestQuoteImpl.call(this, xmrAmount, callback); + public void requestQuote(final double btcAmount, @NonNull final ShiftCallback callback) { + RequestQuoteImpl.call(this, btcAmount, callback); } @Override diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/LegacyStorageHelper.java b/app/src/main/java/com/m2049r/xmrwallet/util/LegacyStorageHelper.java index 68a1f6b..20ea61c 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/util/LegacyStorageHelper.java +++ b/app/src/main/java/com/m2049r/xmrwallet/util/LegacyStorageHelper.java @@ -31,8 +31,7 @@ public class LegacyStorageHelper { try { if (isStorageMigrated(context)) return; if (!hasReadPermission(context)) { - // nothing to migrate, so don't try again - setStorageMigrated(context); + // can't migrate - don't remember this, as the user may turn on permissions later return; } final File oldRoot = getWalletRoot(); diff --git a/app/src/main/res/layout/item_transaction.xml b/app/src/main/res/layout/item_transaction.xml index 00d66df..e210701 100644 --- a/app/src/main/res/layout/item_transaction.xml +++ b/app/src/main/res/layout/item_transaction.xml @@ -1,5 +1,6 @@ - + + + + + + + + diff --git a/app/src/main/res/values-ar/about.xml b/app/src/main/res/values-ar/about.xml new file mode 100644 index 0000000..1d6b13f --- /dev/null +++ b/app/src/main/res/values-ar/about.xml @@ -0,0 +1,48 @@ + + + أغلق + أنا مونيرويو + النسخة %1$s (%2$d) + + الاعتمادات +
+ m2049r, baltsar777, anhdres, keejef, + rehrar, EarlOfEgo, ErCiccione et al. +

+ monerujo.io + ]]>
+ + سياسة الخصوصية +

+ هذه الصفحة تخبرك بسياستنا بخصوص التجميع، الاستخدام، و الافصاح عن المعلومات الشخصيةالتي نستلمها من مستخدمي تطبيقنا (مونيرويو: محفظة مونيرو) +

+

باستخدامك هذا التطبيق أنت توافق تجميع و استخدام المعلومات وفقاً لهذه السياسة +

+

البيانات المجمعة

+

المعلومات الشخصية هي نوع من البيانات التي قد تعرف هوية شخص ما +

+

مفاتيح مونيرو و العناوين العامة مجمعة و معالجة من قبل التطبيق محليا لغرض معالجة المعاملات و هي ترسل الى شبكة مونيرو في حالة مشفرة +

+

لا يجمع التطبيق أي معلومات شخصية أخرى

+

إذا أنت تستخدم خدمة الصراف (اختياري)، مونيرويو يجلب سعر الصرف عبر api coinmarketcap.com. اطلع على سياسة الخصوصية الخاصة بهم على https://coinmarketcap.com/privacy لتفاصيل على كيف تجمع بياناتك التي في الطلب.

+

عندما تستعمل التطبيق لتدفع إلى عنوانين بيتكوين، فأنت تستعمل خدمة SideShift.ai. اطلع على سياسة الخصوصية الخاصة بهم على https://sideshift.ai للتفاصيل. يرسل مونيرويو عنوان بيتوين و المبلغ إليهم. سيأخذ أيضاً عنوان بروتوكول الإنترنت (ip) الخاص بك.

+

صلاحيات التطبيق

+
    +
  • الإنترنت: للإتصال بشبكة مونيرو عبر عقدة مونيرو
  • +
  • قرائة ملفات التخزين الخارجي: لقرائة ملفات المحفظة المخزنة على الجهاز
  • +
  • الكتابة إلى التخزين الخارجي: لكتابة ملفات المحفظة المخزنة على الجهاز
  • +
  • قفل الإيقاظ: لإبقاء الجهاز ياقظاً عند التزامن
  • +
  • الكاميرا: لمسح رموز الاستجابة السريعة (qr) لاستلام مونيرو
  • +
+

التغيرات لسياسة الخصوصية هذه

+

. يمكن أن نحدث سياسة الخصوصية هذه من حين إلى أخرى. سنقوم بتنبيهك لأاي تغيرات بنشر سياسة الخصوصية الجديدة في التطبيق و على الموقع (www.monerujo.io) + ننصحك أن تراجع هذه السياسة بشكل دوري لأاي تغيرات +

آخر تحديث لسياسة الخصوصية هذه كان في 10/11/2017 +

+

تواصل معنا

+

privacy@monerujo.io.إذا كان لديك أي سؤال عن سياستنا أو عن كيفية تجميع بياناتك و معالجتها، الرجاء إرسال بريد الكتروني إلى +

+ ]]>
+
diff --git a/app/src/main/res/values-ar/help.xml b/app/src/main/res/values-ar/help.xml new file mode 100644 index 0000000..3d69d57 --- /dev/null +++ b/app/src/main/res/values-ar/help.xml @@ -0,0 +1,215 @@ + + + أنشئ محفظة - جديدة +

إذا كنت تحتاج إلى عنوان مونيرو جديد!

+

أدخل اسم محفظة و كلمة سر فريدين. + كلمة المرور مستخدمة لتأمين بيانات محفظتك على الجهاز. استخدم كلمة سر قوية - و استخدام عبارة سر أفضل.

+

دون البذرة الذاكرية!

+

سترى في الشاشة التالية \"البذرة الذاكرية\" ذات 25 كلمة خاصة بك. هي كل ما تحتاجه لاسترجاع محفظتك لاحقاً و الحصول على وصول كامل لمالك. + إبقائها آمنة و خاصة مهم جداً، فهي تعطي أي أحد وصولاً كاملاً لمالك!

+

إذا نسيت كلمة مرور محفظتك يمكنك استرجاع محفظتك باستعمال بذرة الذاكرة.

+

ليس هناك طريقة لاسترجاع البذرة الذاكرية، إذا أضعتها ضاع مالك! + أيضاً، لا يمكن لبذرة الذاكرية أن تتغير و إذا ما سرقت أو انفضحت، + عليك أن تحول مالك إلى محفظة جديدة (مع بذرة ذاكرية جديدة). لذا من + الأفضل عمل نسخ احتياطية من بذرتك بكتابتها و تخزينها في أكثر من + مكان آمن

+ ]]>
+ + أنشئ محفظة - بذرة +

إذا لديك عنوان مونيرو و تريد استعادة المعاملات من سلسلة الكتل!

+

أدخل اسم محفظة و كلمة سر فريدين. + كلمة المرور مستخدمة لتأمين بيانات محفظتك على الجهاز. استخدم كلمة سر قوية - و استخدام عبارة سر أفضل.

+

أدخل بذرتك في حقل \"البذرة الذاكيرة\".

+

أدخل رقم الكتلة لأول معاملة لهذا العنوان في حقل \""\. يمكنك أيضاًاستعمال تاريخ في صيغة سسسس-شش-يي. إن لم تكن متأكداً أدخل تاريخ/كتلة تقريبي(ة) قبل استخدامك الأول لهذا العنوان.

+ ]]>
+ + أنشئ محفظة - لدجر +

إذا كنت تسترجع محفظتك من جهاز لدجر نانو اس.

+

مفاتيحك السرية لا تغادر جهاز لدجر، لذا تجتاج إلى توصيله كلما أردت الوصول لمحفظتك.

+

أدخل اسم محفظة و كلمة سر فريدين. كلمة المرور مستخدمة لتأمين بيانات محفظتك على جهاز الأندرويد. استخدم كلمة سر قوية - واستخدام عبارة سر أفضل.

+

أدخل رقم الكتلة لأول معاملة لهذا العنوان في حقل \""\. يمكنك أيضاًاستعمال تاريخ في صيغة سسسس-شش-يي. إن لم تكن متأكداً أدخل تاريخ/كتلة تقريبي(ة) قبل استخدامك الأول لهذا العنوان.

+ ]]>
+ + أنشئ محفظة - مفاتيح +

إذا كنت تسترجع محفظتك باستخدام مفاتيحك!

+

أدخل اسم محفظة و كلمة سر فريدين. كلمة المرور مستخدمة لتأمين بيانات محفظتك على جهاز الأندرويد. استخدم كلمة سر قوية - واستخدام عبارة سر أفضل.

+

أدخل عنوان مونيرو في حقل \"العنوان العام\" و عبئ \"مفتاح الرؤية\" و \"مفتاح الانفاق\".

+

أدخل رقم الكتلة لأول معاملة لهذا العنوان في حقل \""\. يمكنك أيضاًاستعمال تاريخ في صيغة سسسس-شش-يي. إن لم تكن متأكداً أدخل تاريخ/كتلة تقريبي(ة) قبل استخدامك الأول لهذا العنوان.

+ ]]>
+ + أنشئ محفظة - رؤية +

إذا كنت تريد مراقبة المعاملات القادمة إلى المحفظة!

+

أدخل اسم محفظة و كلمة سر فريدين. كلمة المرور مستخدمة لتأمين بيانات محفظتك على جهاز الأندرويد. استخدم كلمة سر قوية - واستخدام عبارة سر أفضل.

+

أدخل عنوان مونيرو ملكك في حقل "\عنوان عام"\ و املأ \مفتاح الرؤية"\".

+

أدخل رقم الكتلة لأول معاملة لهذا العنوان في حقل \""\. يمكنك أيضاًاستعمال تاريخ في صيغة سسسس-شش-يي. إن لم تكن متأكداً أدخل تاريخ/كتلة تقريبي(ة) قبل استخدامك الأول لهذا العنوان.

+ ]]>
+ + تفاصيل المحفظة +

العنوان العام

+ عنوانك العام بمثابة رقم حسابك البنكي يمكنك مشاركته مع أي أحد دون خوف من خسارة مونيرو الخاص بك. يرسل الناس المونيرو إلى محفظتك باستخدام هذا العنوان. +

البذرة الذاكرية

+ هي كل ما تحتاجه لاسترجاع محفظتك و الحصول على وصول كامل لمالك. إبقائها خاصة و آمنة مهم جداًَ، فهي تعطي لي أحد وصولاً كاملاً لمونيرواتك! إذا لم تكتبها في مكان آمن رجاءً افعل! +

كلمة مرور استرجاع ملفات المحفظة

+ تأكد من تدوين كلمة المرور هذه. ستحتاج إليها إذا أعدت ضبط جهازك أو ألغيت تثبيت التطبيق.
+

CrAzYpass

+ إذا كانت كلمة المرور المعروضة هنا هي أبجدية رقمية من 52 جزء في مجموعات من 4 - تهانينا! + ملفات محفظتك مؤمنة باستخدام مفتاح 256 بت مولد باستخدام خصائص أمان جهازك + أساساً على عبارة المرور التي خترتها (عند الإنشاء أو بتغييرها). هذا يجعلها صعبة جداً للاختراق!
+ هذه الميزة اجبارية لكل المحافظ الجديدة. +

كلمة السر القديمة

+ إذا ترى عبارة مرورك هنا، محفظتك ليسب بأمان استخدام CrAzYpass. لإصلاح هذا فقط اختار \"غير كلمة المرور\" من القائمة. بعد إدخالك عبارة مرور جديدة (ربما نفسها القديمة) سيولد التطبيق CrAzYpass لك و سيؤمن ملفات محفظتك به. اكتبه! +

CrAzYpass محافظ

+ إذا احبجت في أي وقت إلى إعادة تثبيت مونيرويو (بعد إعادة ضبط هاتفك أو التبديل إلى جهاز جديد مثلاً) أو إذا أردت استخدام ملفات المحفظة جهاز مختلف أو حاسوب، فيجب عليك استعمال كلمة المرور الاسترجاعية هذه للوصول إلى محفظتك مجدداً.
+ بإختيارك \"غير عبارة المرور\" من القاءمة، يمكنك اختيار عبارة مرور أخرى. انتبة أن هذا سيولد كلمة مرور استرجاعية جديدة. اكتبها! +

مفتاح الرؤية

+ يمكنك استخدام مفتاح الرؤية الخاص بك لمراقبة المعاملات القادمة لمحفظتك دون اعطاء إذن لإنفاق المال داخل محفظتك. +

مفتاح الإنفاق

+ مفتاح الانفاق الخاص بك يسمح لأي شحص بانفاق المونيرو المتعلق بمحفظتك، لذا لا تخبر أجداً بالمفتاح. أبقه آمناً كبذرة الذاكرية. + ]]>
+ + قائمة المحافظ +

العقدة

+

.مونيرويو يستخدم عقدة بعيدة للاتصال بشبكة مونيرو دون الحاجة إلى تنزيل و الاحتفاظ بنسخة كاملة من سلسة الكتل. يمكنك العثور على قائمة من العقد الشائعة أو تعلم كيف تشغل عقدة خاصة بك هنا https://moneroworld.com

+

يأتي مونيرويو مع بعض العقد البعيدة المحددة مسبقاً. مونيرويو يتذكر آخر خمس عقد مستخدمة.

+ +

المحافظ

+

هنا ترى محافظك. هن موجودات في مجلد monerujo في التخزين الداخلى لجهازك. + يمكنك استعمال تطبيق مستكشف ملفات لرؤيتهن. ينبغي عليك عمل نسخ احتياطية من هذا المجلد + على أسس منتظمة لتخزين خارج جهازك في حالة انفجاره أو سرقته

+

اختر محفظة لتفتحها أو المس زر \"+\" لإنشاء واحدة جديدة. أو اختر واحدة من عمليات المحفظة:

+

التفاصيل

+

أظهر تفاصيل المحفظة، البذرة و المفاتيح.

+

استلم

+

أنشئ رمز استجابة سريعة(qr code) لاستلام المونيرو.

+

أعد التسمية

+

أعد تسمية المحفظة. النسخ الاحتياطية لا تعاد التسمية.

+

نسخة احتياطية

+

أنشئ نسخة من المحفظة في مجلد backups داخل مجلد monerujo مستبدلة النسخ السابقة هناك.

+

أرشيف

+

أنشئ نسخة احتياطية ثم احذف المحفظة. النسخة تبقى في مجلد backups إذا لم تعد بحاجة إلى نسخك الاحتياطية ينبغي أن تحذفهم باستعمال متصفح ملفات أو تطبيق حذف آمن.

+ ]]>
+ + تفاصيل المعاملة +

الوجهة

+ هذا هو العنوان العام للمحفظة التي تريد إرسال مونيرو إليها. +

معرف الدفع

+ يمكنك استخدام معرف دفع لتعريف السبب لارسالك مونيرو بين طرفين. هذا اختياري + و خاص. فمثلاً يسمح لشركة بتسوية معاملتك مع غرض شريته. +

TX ID

+ هذا هو معرف معاملتك. يمكنك استخدامه لتعريف معاملتك المشوشة في مستكشف سلسلة كتل مونيرو مثل https://xmrchain.net/ +

TX KEY (مفتاح المعاملة)

+ هذا هو مفتاح معاملتك الخاص، أبقه آمناً فإظهاره إلى طرف ثالث يظهر أي توقيع في (حلقة/طوق/خاتم) هو الخاص بك، جاعلاً معاملاتك شفافة. +

كتلة

+ هذه هي الكتلة التي تحتوي معاملتك. + ]]>
+ + أرسل +

عنوان المستلم

+

هذا هو العنوان العام للمحفظة التي تريد إرسال مونيرو إليها، يمكنك نسخه من الحافظة + ، مسح رمز استجابة سريعة (QR) أو إدخاله يدوياً. تأكد من العنوان لضمان عدم الارسال إلى عنوان خطأ.

+

بالإضافة إلى عنوان مونيرو يمكنك استعمال +

    +
  • مفتوحة (OpenAlias) لXMR أو BTC
  • +
  • عنوان بيتكوين
  • + + يرجى ملاحظة أن إرسال BTC يتم من خلال خدمة Sideshift.ai (انظر https://sideshift.ai + للتفاصيل). راجع قسم إرسال BTC أدناه.

    +

    معرف الدفع

    +

    يمكنك استخدام معرف دفع لتعريف السبب لارسالك مونيرو بين طرفين. هذا اختياري + و خاص. فمثلاً يسمح لشركة بتسوية معاملتك مع غرض شريته

    +

    إرسال بيتكوين

    +

    SideShift.ai

    +

    Sideshift.ai خدمة طرف ثالث تعمل كصرافة من مونيرو إلى بيتكوين. نستخدم API Sideshift.ai لإدراج دفع بيتكوين في مونيرويو. رجاءاً اطلع على https://sideshift.ai و قرر لنفسك إذا ما كانت جدمة تريد استخدامها. فريق مونيرويو ليس مرتبطاً بSideshift.ai ولا يمكنه مساعدتك مع خدمتهم

    +

    SideShift.ai سعر صرف

    +

    في شاشة \"المبلغ\" ستعرض عليك الضوابط الحالية لخدمة Sideshift.ai + هذه الضوابط تتضمن سعر الصرف الحالي بالإضافة إلى حدود BTC الدنيا و العليا. لاحظ أن هذا السعر ليس مضموناً في هذه المرحلة

    +

    SideShift.ai طلب

    +

    في شاشة \"أكد\" سترى طلب Sideshift.ai الفعلي. هذا الطلب صحيح لفترة محدودة + قد تلاحظ عداًَ تنازلياً على زر \"spend\". قد يكون سعر الصرف مختلفاً عن السعر الدلالي في الشاشة السابقة

    +

    السري SideShift.ai مفتاح

    +

    لأن مونيرويو فقط يتعامل مع جزء مونيرو من معاملتك يمكن لمفتاح Sideshift.ai السري الخاص البك أن يستعل لتتبع جزء بيتكوين من طلبك على موقع Sideshift.ai

    +

    SideShift.ai عد تنازلي

    +

    عند وصول العد التنازلي إلى الصفر، تحتاج إلى الحصول على سعر جديد من Sideshift.ai بالرجوع إلى الخطوة السابقة ثم العودة إلى شاشة \"أكد\"

    + ]]> + + إرسال بيتكوين +

    SideShift.ai

    +

    Sideshift.ai خدمة طرف ثالث تعمل كصرافة من مونيرو إلى بيتكوين. نستخدم API Sideshift.ai لإدراج دفع بيتكوين في مونيرويو. رجاءاً اطلع على https://sideshift.ai و قرر لنفسك إذا ما كانت جدمة تريد استخدامها. فريق مونيرويو ليس مرتبطاً بSideshift.ai ولا يمكنه مساعدتك مع خدمتهم.

    +

    SideShift.ai سعر صرف

    +

    في شاشة \"المبلغ\" ستعرض عليك الضوابط الحالية لخدمة Sideshift.ai + هذه الضوابط تتضمن سعر الصرف الحالي بالإضافة إلى حدود BTC الدنيا و العليا. لاحظ أن هذا السعر ليس مضموناً في هذه المرحلة.

    +

    SideShift.ai طلب

    +

    في شاشة \"أكد\" سترى طلب Sideshift.ai الفعلي. هذا الطلب صحيح لفترة محدودة + قد تلاحظ عداًَ تنازلياً على زر \"spend\". قد يكون سعر الصرف مختلفاً عن السعر الدلالي في الشاشة السابقة.

    +

    السري SideShift.ai مفتاح

    +

    لأن مونيرويو فقط يتعامل مع جزء مونيرو من معاملتك يمكن لمفتاح Sideshift.ai السري الخاص البك أن يستعل لتتبع جزء بيتكوين من طلبك على موقع Sideshift.ai

    +

    التنازلي! SideShift.ai عد

    +

    عند وصول العد التنازلي إلى الصفر، تحتاج إلى الحصول على سعر جديد من Sideshift.ai بالرجوع إلى الخطوة السابقة ثم العودة إلى شاشة \"أكد\"

    + + المحفظة +

    وضع الشارع

    +

    + يمكنك تفعيل/تعطيل وضع الشارع في القائمة أو أيقونة رأس غونثر. في هذا الوضع، رصيدك لا يظهر على أي شاشة لذا يمكنك استخدام محفظتك بأمان في الشارع، القهوة، أو أي مكان عام. المعاملات السابقة أيضاً مخفية. ستعرض المعاملات الجديدة لترى أنك أرسلت/استلمت موينرو.

    +

    مسح

    + لأن مونيرو يحب إبقاء الأشياء خاصة، كل مرة تفتح محفظة موينيرويو علينا مسح سلسلة الكتل لنرى إذا ما أرسل مونيرة إلى محفظتك. أحياناً يستغرق فترةً لأنك لم تزامن منذ فترة طويلة. +

    الرصيد

    +

    النجدة! رصيد محفظتي اختفى أو هو غير مؤكد!
    + لا تفزع! عندما ترسل المال من محفظتك، بعض رصيدك سيظهر مؤقتاً كغير مؤكد. + يحصل نتيجةً لكيفية تبادل مونيرو على سلسلة الكتل و كيفية عمل الفكة. إقرأ أكثر عن الفكة على https://getmonero.org/resources/moneropedia/change.html +

    قائمة المعاملات

    +

    في محافظ الرؤية، فقط تعرض المعاملات القادمة.

    + ]]>
    + + العقد +

    المختصر المفيد

    +

    أعد تحميل قائمة العقد بالسحب للأسفل & bookmark 3–5 عقد لتسمح لمونيرويو أن يختار الأفضل لك!

    +

    ما هي العقد؟

    +

    مونيرويو يستخدم عقدة خارجية لالتواصل بشبكة مونيرو دون الحاجة لتنزيل نسخة كاملة من سلسلة الكتل .

    +

    قائمة العقد

    +

    إذا القائمة فارغة، يمكنك إما إضافة العقد يدوياً أو دع مونيرويو يمسح الشبكة لك. أو كلا الأمرين. إقرأ أكثر…

    +

    تعرض قائمة العقد كل العقد المعروفة حالياً. إضافةً، الطابع \ الختم الزمني لأحدث كتلة معروفة لكل عقدة يظهر + تحت اسم العقدة. تظهر أيقونة تمثل سلوك استجابة العقدة (يشير إلى مستوى الاتصال المتوقع) بجانب كل عقدة.

    +

    أي عقدة في القائمة يمكن أن تعلم لاستعمال لاحق. + العقد التي لم تعلم ستنسى.

    +

    سيختار مونيرويو العقدة المعلمة الأمثل كل مرة تستعمله. + يفعل هذا بالتأكد من ارتفاع الكتلة (ما هي حداثة العقدة؟) + إضافة إلى استجابتها (ما سرعة استجابة العقدة للطلبات؟).

    +

    هذه القائمة مفروزة حسب هذه الخصائص، فالعقدة العليا هي التي يختارها مونيرويو الآن. سيظهر الجزء السفلى عقد بطيئة جداً أو غير متوفرة.

    +

    أضف عقدة

    +

    عند لمس زر "أضف عقدة" في الأسفل، سيطلب منك إدخال تفاصيل العقدة في الحوار التالى. + "العنوان" هو اسم المضيف أو عنوان IP للعقدة - هذا المدخل الإلزامي الوحيد. + أدخل "المنفذ" إذا تشتغل العقدة في منفذ غير افتراضي )18089) + يمكنك أيضاً تسمية العقدة لتتمكن من التعرف عليها بسهولة في وقت لاحق. + بعض العقد تتطلب بيانات اعتماد لاستخدامهم. أدخل اسم المستخدم و كلمة المرور المزودين في الحقول المناسبة. الآن يمكنك "اختبار" هذه الاعدادات. + ستعرض "نتائج الاختبار" ارتفاع الكتلة، وقت الاستجابة، و عنوان IP المستعمل. + قد تكون النتيجة خطأً - عادة لأن اسم المصيف المزود لا يمكن الوصول إليه في وقت معقول أو أن بيانات الاعتماد غير صحيحة.أو أن اسم المضيف/المنفذ لا يشيران إلى عقدة مونيرو حقيقية! + عند اجتياز الاختبار (لا اخطاء) - يمكنك لمس "حسناً" لحفظ و تعليم هذه العقدة

    +

    ابحث عن العقد

    +

    إضافةً، يمكنك مسح الشبكة للعقد. مونيرويو سيبدأ مسح الشبكة للعقد البعيدة في منفذ 18098. يبدأ بيؤال العقد المعلمة عن أنداد آخرين في شبكة مونيرو ثم يستمر بسؤالهم عن أندادهم، وهكذا. إذا لا تملك عقد معلمة (أو لا يخبروننا عن أندادهم)، مونيرويو سيتجه مباشرةً إلى عقد بذور مونيرو ضمن مونيرو. سيتوقف المسح عند العثور على 10 عقد بعيدة.

    + ]]>
    + + استخدام رابط دفع +

    لقد بدأت مونيرويو باستخدام رابط دفق. لإرسال المال افعل التالي:

    +

    + 1. المحفظة التي تريد الانفاق منها
    + 2. انتظر حتى تزامن المحفظة وamp; يظهر زر "أعط"
    + 3. المس زر "أعط" +

    +

    .ستعبأ تفاصيل الدفع. تأكد منهم ثم أكمل كأي معاملة أخرى

    + ]]>
    + + فهمت! + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml new file mode 100644 index 0000000..6952765 --- /dev/null +++ b/app/src/main/res/values-ar/strings.xml @@ -0,0 +1,418 @@ + + + محفظة + + عن + سياسة الخصوصية + + شارك + ساعدني + استلم + أعد التسمية … + انشئ نسخة احتياطية + غير كلمة المرور + + … أكمل الكتابة + … مه + هيا يمكنك القيام بأفضل من هذا! + تكاد تصل … + أجل، كالمحترفين! + + المحافظ + الاعتمادات + حسناً + إلغاء + أغلق + المس لالتفاصيل + + نجح الإرسال + تم + + المس لرمز استجابة سريعة (qr) + + دفع BTC مفعل، المس لمعلومات أكثر. + لدجر مفعل، المس لمعلومات أكثر. + + أدخلت عنوان بيتكوين.
    + سترسل XMR و سيستلم المستلم BTC باستخدام خدمة Sideshift.ai + ]]>
    + + Sideshift.ai طلب + + %1$s BTC + + التأكيد معلق + الدفع معلق + Sideshift.ai عطل (%1$s) + BTC أرسل + جار الاستعلام … + + يمكنك إرسال %1$s — %2$s BTC.
    + Sideshift.ai يعطيك سعر صرف %3$s BTC حالياً. + ]]>
    + + الرصيد: %2$s BTC (%1$s XMR) + + ✔ معرف الدفع مدمج + تجهيز عمليتك + + جار إنشاء طلب Sideshift.ai + استعلام طلب Sideshift.ai + جار تجهيز معاملة مونيرو + + استعلام ضوابط Sideshift.ai + + Sideshift.ai عطل + رمز: %1$d + + المس لإعادة المحوالة + علقنا هنا! + يبدو أن Sideshift.ai ليس متوفراً حالياً! + + %1$s BTC = %2$s XMR + (الصرف: %1$s BTC/XMR) + + قم بزيارة Sideshift.ai للدعم و التتبع + المفتاح السري\nSideshift.ai + السري Sideshift.ai مفتاح + عنوان الوجهة BTC + المبلغ + + معرف المعاملة + عنوان الوجهة + ملاحظات + + جار إنشاء النسخة الاحتياطية + جار الأرشفة + جار إعادة التسمية + جار تغيير كلمة المرور + + جار اختتام الأمور …\nقد يستغرق هذا برهةً! + + نجح النسخ الاحتياطي + فشل النسخ الاحتياطي! + فشلت إعادة التسمية! + فشل تغيير كلمة السر! + تم تغيير كلمة السر + + العقدة + جار تحميل المحفظة … + حفظت المحفظة + فشل حفظ المحفظة! + جار الاتصال … + فشل الاتصال بالعقدة!\nتأكد من اسم المستخدم/كلمة المرور + نسخة العقدة غير متوافقة - حدث رجاءً! + العقدة غير صحيحة!\nجرب عقدة أخرى. + لا يمكن الوصول للعقدة!\nحاول مجدداً أو جرب عقدة أخرى. + + منقطعة + + فشلت المعاملة: %1$d + + !انتظرت طويلاً يا صاحبي! + + …ما زلت مشغولاً بمحفظتك الأخيرة + + أعد التسمية %1$s + + كلمة مرور جديدة ل %1$s + أعد كلمة المرور ل %1$s + كلمة السر ل%1$s + يمكنك أيضاً فتح المحفظة باستعمال البصمة.\nرجاءً المس الحساس. + جار فتح المحفظة… + لم يتعرف على البصمة. حاول مجدداً. + كلمة السر خاطئة! + كلمة المرور المحفوظة غير صحيحة.\nرجاءً أدخل كلمة المرور يدوياً. + المحفظة غير موجودة! + !يجب ضبط العقدة! + المحفظة لا تطابق الشبكة المختارة + + (مشاهدة فقط) + + استلم + أعط + + + %1$s XMR غير مأكد + + خدمة مونيرويو + + تزامن؛ + الكتل التبقية + جار مسح: + + التخرين الخارجي غير قابل للكتابة! افزع! + نحتاج إلى صلاحيات التزين الخارجي فعلاً! + لا كاميرا = لا مسح لرموز الاستجابة السريعة (QR)! + + مفتاح الرؤية + العنوان العام + Sideshift.ai مفتاح + نسخ مفتاح الرؤية إلى الحافظة! + نسخ مفتاح Sideshift.ai إلى الناسخة! + نسخ عنوان المحفظة للحافظة! + نسخ معرف المعاملة إلى الحافظة! + النسخ معطل لأسباب أمنية! + + لا يمكن الحصول على سعر الصرف!\nاستعمل XMR/XMR أو حاول مجدداً + + أنشئ محفظة + اسم المحفظة + كلمة مرور المحفظة + اسمح لفتح المحفظة بالبصمة + التوثيق بالبصمة +

    عند تفعيل التوثيق بالبصمة، يمكنك رؤية رصيد المحفظة و استلام المال دون ادخال كلمة السر.

    +

    لكن لزيادة الأمان، مونيرويو سيتطلب منك أن تدخل كلمةالمرور عند رؤية تفاصيل المحفضة أو إرسال المال.

    + تحذير أمني + +

    مثلا، ينكن لشخص خبيث فتح محفظتك و أنت نائم.

    + هل أنت متأكد أنك تريد تفعيل هذه ال + ]]>
    + السر لا تتطابق + لا يمكن لعبارة المرور أن تكون فارغة + انشئ لي محفظة و خلصنا! + دونت بذرة الذاكرة + + أعطني اسماً + المحفظة موجودة! + لا يمكن البدء ب. + جار إنشاء المحفظة + أنشأت المحفظة + + أدخل رقماً أو تاريخاً (سسسس-شش-يي) + + المفاتيح + جديد + بذرة + رؤية + + العنوان العام + مفتاح الرؤية + مفاح الإنفاق + بذرة الذاكرة ذات 25 كلمة + استرجع الارتفاع أو التاريخ (سسسس-شش-يي) + + العنوان العام + مفتاح الرؤية + مفتاح الإنفاق + بذرة الذاكرة + ملفات المحفظة استرجع كلمة المرور + + أدخل مفتاحاً صحيحاً + أدخل عنواناً صحيحاً + أدخل بذرتك ذات 25 كلمة + + الملاحظات الخاصة (اختياري) + ولد + أنفق مونيرواتي الحبيبة + أرسل مونيرواتي الحبيبة (%1$s) + ليس رمز استجابة سريعة (QR) + ليس رمزاً حصيحاً + ليس عنواناً صحيحاً + عنوان OpenAlias ليس متوفر + آمن ✔ + حل OpenAlias… + OpenAlias دون DNSSEC - قد يكون العنوان منتحل + أرسل + الرصيد: %1$s XMR + العنوان + المبلغ + أكد + تم + + المبلغ + الرسوم (xmr) + الرسوم + المجموع (xmr) + المجموع + + %1$s XMR + +%1$s رسوم + + عطل إنشاء المعاملة + + - رسوم %1$s + (%1$s) + فشل + - %1$s + + %1$s + + الختم الزمني + TX ID + TX Key + الوجهة + معرف الدفع + الكتلة + المبلغ + الرسوم + التحويلات + ملاحظات + (اختياري) + تفاصيل المعاملة + + معلقة + فشلت + + المبلغ + وصف (اختياري) + لم يتمكن من فتح المحفظة! + + %1$s أقصى + 0 أدنى + XMR ليس رقماً + + ستظهر بيانات حساسة.\nتفحص خلف ظهرك! + أنا في أمان + أرجعني! + التفاصيل + + أنشئ محفظة جديدة + استرجع محفظة رؤية-فقط + استرجع محفظة من المفاتيح الخاصة + استرجع محفظة من بذرة 25 كلمة + + أنشئ حساباً + أضيف حساب جديد #%1$d + الحساب # + + أرسل كل المال المؤكد في هذا الحساب! + العنوان الفرعي #%1$d + العنوان الفرعي العام #%1$d + + اللغة + استخدم لغة النظام + + استرجع من لدجر نانو اس + + جار التواصل مع اللدجر + التأكيد على اللدجر مطلوب! + استلام العناوين الفرعية + التأكد من صحة المفاتيح + القيام بحسابات مجنونة + تشفير الأشياء + رجاءً (إعادة) إيصال جهاز لدجر + + جار إنشاء الحساب + + %1$s اربط + %1$s فصل + + جار كتابة العلامة + فشلت كتابة العلامة + نجحت كتابة العلامة + العلامة لا تدعم NDEF! + العلامة تزود %1$dلأ بايتاً، لكننا نحتاج %2$ل! + لا أفهم العلامة! + لا أعرف ماذا تريد! + NFC متوفر! + + أظهر أسراري! + وضع الشارع + + Node-o-matiC مفعل، المس لمعلومات أكثر. + آخر كتلة تحدثت: %1$s + العقد + اسم العقدة (اختياري) + اسم المضيف + المنفظ + اسم المستخدم (اختياري) + كلمة المرور (اختياري) + لا يمكن حل المضيف + نحتاج لهذا! + يجب أن يكون رقماً + 1–65535 يجب أن يكون + أضف عقدة + المس لإعادة التحميل + %1$d عطل إطصال + عطل في الاتصال + فشل التوثيق + نتيجة الاختبار: + الارتفاع: %1$s (v%2$d), Ping: %3$.0fms, IP: %4$s + اختبار IP: %1$s … + رجاءً انتظر انتهاء المسح + المس لاختيار أو إضافة العقد + أضف العقد يدوياً أو اسحب للأسفل للمسح + جار مسح الشبكة… + علمت أفضل %1$d عقد تلقائياً + اختبر + + المستلم + + كل شيء! + + حول بذرة اللدجر + كلمات بذرة اللدجر + عبارة دخول اللدجر (متقدم) + بذرة اللدجر غير صحيحة! + إدخال بذرة اللدجر هنا خطر أمني كبير! + + استرجع الارتفاع + + ابدأ تطبيق مونيرو في %1$s + + أعد المسح! + + فهمت! + التالي + أنا جاهز! + + مرحباً بك في مونيرويو! + هذا التطبيق يسمح لك بإنشاء و استخدام محافظ مونيرو. يمكنك الاحتفاظ بالحبيب مونيرو فيهم. + أبق بذرتك آمنة + البذرة تمنح وصولاً كاملاً لمن يمتلكها.إذا ما أضعتها لا يمكننا مساعدتك في استرجاعها و ستخسر مونيرواتك الحبيبة. + أرسل بيتكوين + لدى مونيرويو دعم داخلي لSideshift.ai. فقط الصق أو امسح عنوان بيتكوين و سترسل بيتكون بانفاق مونيرو. + العقد، كما تشاء + العقد تصلك بشبكة مونيرو. اختر ما بين العقد العامة أو كن متمرداً سبرانياً و استخدم خاصتك. + أرسل بالبصمة + يمكنك الآن إرسال XMR فقط ببصمتك إذا فعلتها. لطلب كلمة المرور، فقط عطل الدخول بالبصمة. + + الوضع الليلي + + تلقائي + يوم + ليل + + لا شيء هنا\nالرجاء إنشاء أو استعادة محفظة + + أرجع العقد الافتراضية + الاسترجاع يتقدم بالفعل... + + الكتلة الأخيرة: منذ %1$d ثوان + الكتلة الخيرة: منذ %1$d ساعة + الكتلة الأخيرة: منذ %1$d ساعة + الكتلة الأخيرة: منذ %1$d أيام + + لا يمكن الحصول على سعر + تأكد من البلغ و حاول مجدداً + عنوان مبهم.
    + رجاء حدد النوع أعلاه. + ]]>
    + + رجاء أدخل أو امسح عنوان %1$s
    + سترسل XMR و سيتلقى المستلم %2$s باستعمال خدمة SideShift.ai + ]]>
    + + رجاء أدخل أو امسح عنوان مونيرو + ]]> + + العناوين الفرعية + اسم العنوان الفرعي + عناوين غير مستعملة كثيرة - استعمل بعضها لتتمكن من إنشاء المزيد! + حسابات غير مستعملة كثيرة - استعمل بعضها لتتمكن من إنشاء المزيد! + المعاملات لهذا العنوان الفرعي: + لا معاملات لهذا العنوان الفرعي بعد + اختر عنواناً فرعياً + المس طويلاً للتفاصيل + + استورد محفظة + فشل الاستيراد + + أعد ضبط المحفظة! + ستتم إعادة ضبط هذه المحفظة ، وفقدان جميع البيانات خارج السلسلة (مثل الملاحظات ، وأسماء الحسابات والعناوين الفرعية ، ومفاتيح المعاملات الخاصة ، ...)! استخدم هذا فقط إذا كانت هذه المحفظة تالفة و لا تحمل! +
    diff --git a/app/src/test/java/com/m2049r/xmrwallet/service/shift/sideshift/SideShiftApiRequestQuoteTest.java b/app/src/test/java/com/m2049r/xmrwallet/service/shift/sideshift/SideShiftApiRequestQuoteTest.java index e6980a8..d5a112e 100644 --- a/app/src/test/java/com/m2049r/xmrwallet/service/shift/sideshift/SideShiftApiRequestQuoteTest.java +++ b/app/src/test/java/com/m2049r/xmrwallet/service/shift/sideshift/SideShiftApiRequestQuoteTest.java @@ -95,7 +95,7 @@ public class SideShiftApiRequestQuoteTest { @Test public void requestQuote_shouldContainValidBody() throws InterruptedException { - final String validBody = "{\"depositAmount\":\"1.01\",\"settleMethod\":\"btc\",\"depositMethod\":\"xmr\"}"; + final String validBody = "{\"settleAmount\":\"1.01\",\"settleMethod\":\"btc\",\"depositMethod\":\"xmr\"}"; xmrToApi.requestQuote(1.01, mockXmrToCallback); RecordedRequest request = mockWebServer.takeRequest(); @@ -106,18 +106,18 @@ public class SideShiftApiRequestQuoteTest { @Test public void requestQuote_wasSuccessfulShouldRespondWithQuote() throws TimeoutException { - final double xmrAmount = 1.01; + final double btcAmount = 1.01; final double rate = 0.00397838; final String uuid = "66fc0749-f320-4361-b0fb-7873576cba67"; MockResponse jsonMockResponse = new MockResponse().setBody( - createMockRequestQuoteResponse(xmrAmount, rate, uuid)); + createMockRequestQuoteResponse(btcAmount, rate, uuid)); mockWebServer.enqueue(jsonMockResponse); - xmrToApi.requestQuote(xmrAmount, new ShiftCallback() { + xmrToApi.requestQuote(btcAmount, new ShiftCallback() { @Override public void onSuccess(final RequestQuote quote) { - waiter.assertEquals(quote.getBtcAmount(), xmrAmount * rate); - waiter.assertEquals(quote.getXmrAmount(), xmrAmount); + waiter.assertEquals(quote.getXmrAmount(), btcAmount / rate); + waiter.assertEquals(quote.getBtcAmount(), btcAmount); waiter.assertEquals(quote.getId(), uuid); waiter.resume(); } @@ -181,17 +181,17 @@ public class SideShiftApiRequestQuoteTest { waiter.await(); } - private String createMockRequestQuoteResponse(final double xmrAmount, final double rate, + private String createMockRequestQuoteResponse(final double btcAmount, final double rate, final String uuid) { return "{\n" + "\"createdAt\":\"2021-02-04T13:09:14.484Z\",\n" + - "\"depositAmount\":\"" + xmrAmount + "\",\n" + + "\"settleAmount\":\"" + btcAmount + "\",\n" + "\"depositMethod\":\"xmr\",\n" + "\"expiresAt\":\"2021-02-04T13:24:14.484Z\",\n" + "\"id\":\"" + uuid + "\",\n" + "\"rate\":\"" + rate + "\",\n" + - "\"settleAmount\":\"" + (xmrAmount * rate) + "\",\n" + + "\"depositAmount\":\"" + (btcAmount / rate) + "\",\n" + "\"settleMethod\":\"btc\"\n" + "}"; } diff --git a/build.gradle b/build.gradle index 1566259..82af1b6 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:4.2.2' + classpath 'com.android.tools.build:gradle:7.0.2' } } diff --git a/external-libs/android32.Dockerfile b/external-libs/android32.Dockerfile new file mode 100644 index 0000000..93e60ee --- /dev/null +++ b/external-libs/android32.Dockerfile @@ -0,0 +1,151 @@ +FROM debian:stable + +RUN set -x && apt-get update && apt-get install -y unzip automake build-essential curl file pkg-config git python libtool libtinfo5 + +WORKDIR /opt/android +## INSTALL ANDROID SDK +ENV ANDROID_SDK_REVISION 4333796 +ENV ANDROID_SDK_HASH 92ffee5a1d98d856634e8b71132e8a95d96c83a63fde1099be3d86df3106def9 +RUN set -x \ + && curl -s -O https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \ + && echo "${ANDROID_SDK_HASH} sdk-tools-linux-${ANDROID_SDK_REVISION}.zip" | sha256sum -c \ + && unzip sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \ + && rm -f sdk-tools-linux-${ANDROID_SDK_REVISION}.zip + +## INSTALL ANDROID NDK +ENV ANDROID_NDK_REVISION 17c +ENV ANDROID_NDK_HASH 3f541adbd0330a9205ba12697f6d04ec90752c53d6b622101a2a8a856e816589 +RUN set -x \ + && curl -s -O https://dl.google.com/android/repository/android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \ + && echo "${ANDROID_NDK_HASH} android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip" | sha256sum -c \ + && unzip android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \ + && rm -f android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip + +ENV WORKDIR /opt/android +ENV ANDROID_SDK_ROOT ${WORKDIR}/tools +ENV ANDROID_NDK_ROOT ${WORKDIR}/android-ndk-r${ANDROID_NDK_REVISION} +ENV PREFIX /opt/android/prefix + +ENV TOOLCHAIN_DIR ${WORKDIR}/toolchain- +RUN set -x \ + && ${ANDROID_NDK_ROOT}/build/tools/make_standalone_toolchain.py \ + --arch arm \ + --api 21 \ + --install-dir ${TOOLCHAIN_DIR} \ + --stl=libc++ + +#INSTALL cmake +ARG CMAKE_VERSION=3.14.6 +ARG CMAKE_HASH=82e08e50ba921035efa82b859c74c5fbe27d3e49a4003020e3c77618a4e912cd +RUN set -x \ + && cd /usr \ + && curl -L -s -O https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ + && echo "${CMAKE_HASH} cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz" | sha256sum -c \ + && tar -xzf /usr/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ + && rm -f /usr/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz +ENV PATH /usr/cmake-${CMAKE_VERSION}-Linux-x86_64/bin:$PATH + +## Boost +ARG BOOST_VERSION=1_70_0 +ARG BOOST_VERSION_DOT=1.70.0 +ARG BOOST_HASH=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 +RUN set -x \ + && curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \ + && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \ + && tar -xvf boost_${BOOST_VERSION}.tar.bz2 \ + && rm -f boost_${BOOST_VERSION}.tar.bz2 \ + && cd boost_${BOOST_VERSION} \ + && ./bootstrap.sh --prefix=${PREFIX} + +ENV HOST_PATH $PATH +ENV PATH $TOOLCHAIN_DIR/arm-linux-androideabi/bin:$TOOLCHAIN_DIR/bin:$PATH + +ARG NPROC=1 + +# Build iconv for lib boost locale +ENV ICONV_VERSION 1.16 +ENV ICONV_HASH e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04 +RUN set -x \ + && curl -s -O http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \ + && echo "${ICONV_HASH} libiconv-${ICONV_VERSION}.tar.gz" | sha256sum -c \ + && tar -xzf libiconv-${ICONV_VERSION}.tar.gz \ + && rm -f libiconv-${ICONV_VERSION}.tar.gz \ + && cd libiconv-${ICONV_VERSION} \ + && CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ./configure --build=x86_64-linux-gnu --host=arm-linux-androideabi --prefix=${PREFIX} --disable-rpath \ + && make -j${NPROC} && make install + +## Build BOOST +RUN set -x \ + && cd boost_${BOOST_VERSION} \ + && ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --with-locale --build-dir=android --stagedir=android toolset=clang threading=multi threadapi=pthread target-os=android -sICONV_PATH=${PREFIX} install -j${NPROC} + +#Note : we build openssl because the default lacks DSA1 + +# download, configure and make Zlib +ENV ZLIB_VERSION 1.2.11 +ENV ZLIB_HASH c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 +RUN set -x \ + && curl -s -O https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \ + && echo "${ZLIB_HASH} zlib-${ZLIB_VERSION}.tar.gz" | sha256sum -c \ + && tar -xzf zlib-${ZLIB_VERSION}.tar.gz \ + && rm zlib-${ZLIB_VERSION}.tar.gz \ + && mv zlib-${ZLIB_VERSION} zlib \ + && cd zlib && CC=clang CXX=clang++ ./configure --static \ + && make -j${NPROC} + +# open ssl +ARG OPENSSL_VERSION=1.0.2p +ARG OPENSSL_HASH=50a98e07b1a89eb8f6a99477f262df71c6fa7bef77df4dc83025a2845c827d00 +RUN set -x \ + && curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ + && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \ + && tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \ + && rm openssl-${OPENSSL_VERSION}.tar.gz \ + && cd openssl-${OPENSSL_VERSION} \ + && sed -i -e "s/mandroid/target\ armv7\-none\-linux\-androideabi/" Configure \ + && CC=clang CXX=clang++ \ + ./Configure android-armv7 \ + no-asm \ + no-shared --static \ + --with-zlib-include=${WORKDIR}/zlib/include --with-zlib-lib=${WORKDIR}/zlib/lib \ + --prefix=${PREFIX} --openssldir=${PREFIX} \ + && make -j${NPROC} \ + && make install + +# ZMQ +ARG ZMQ_VERSION=v4.3.2 +ARG ZMQ_HASH=a84ffa12b2eb3569ced199660bac5ad128bff1f0 +RUN set -x \ + && git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \ + && cd libzmq \ + && test `git rev-parse HEAD` = ${ZMQ_HASH} || exit 1 \ + && ./autogen.sh \ + && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=arm-linux-androideabi --enable-static --disable-shared \ + && make -j${NPROC} \ + && make install + +# Sodium +ARG SODIUM_VERSION=1.0.18 +ARG SODIUM_HASH=4f5e89fa84ce1d178a6765b8b46f2b6f91216677 +RUN set -x \ + && git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} \ + && cd libsodium \ + && test `git rev-parse HEAD` = ${SODIUM_HASH} || exit 1 \ + && ./autogen.sh \ + && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=arm-linux-androideabi --enable-static --disable-shared \ + && make -j${NPROC} \ + && make install + +COPY . /src +ARG NPROC=4 +RUN set -x \ + && cd /src \ + && CMAKE_INCLUDE_PATH="${PREFIX}/include" \ + CMAKE_LIBRARY_PATH="${PREFIX}/lib" \ + ANDROID_STANDALONE_TOOLCHAIN_PATH=${TOOLCHAIN_DIR} \ + USE_SINGLE_BUILDDIR=1 \ + PATH=${HOST_PATH} make release-static-android-armv7-wallet_api -j${NPROC} + +RUN set -x \ + && cd /src/build/release \ + && find . -path ./lib -prune -o -name '*.a' -exec cp '{}' lib \; diff --git a/external-libs/android32_x86.Dockerfile b/external-libs/android32_x86.Dockerfile new file mode 100644 index 0000000..7e763ac --- /dev/null +++ b/external-libs/android32_x86.Dockerfile @@ -0,0 +1,151 @@ +FROM debian:stable + +RUN set -x && apt-get update && apt-get install -y unzip automake build-essential curl file pkg-config git python libtool libtinfo5 + +WORKDIR /opt/android +## INSTALL ANDROID SDK +ENV ANDROID_SDK_REVISION 4333796 +ENV ANDROID_SDK_HASH 92ffee5a1d98d856634e8b71132e8a95d96c83a63fde1099be3d86df3106def9 +RUN set -x \ + && curl -s -O https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \ + && echo "${ANDROID_SDK_HASH} sdk-tools-linux-${ANDROID_SDK_REVISION}.zip" | sha256sum -c \ + && unzip sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \ + && rm -f sdk-tools-linux-${ANDROID_SDK_REVISION}.zip + +## INSTALL ANDROID NDK +ENV ANDROID_NDK_REVISION 17c +ENV ANDROID_NDK_HASH 3f541adbd0330a9205ba12697f6d04ec90752c53d6b622101a2a8a856e816589 +RUN set -x \ + && curl -s -O https://dl.google.com/android/repository/android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \ + && echo "${ANDROID_NDK_HASH} android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip" | sha256sum -c \ + && unzip android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \ + && rm -f android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip + +ENV WORKDIR /opt/android +ENV ANDROID_SDK_ROOT ${WORKDIR}/tools +ENV ANDROID_NDK_ROOT ${WORKDIR}/android-ndk-r${ANDROID_NDK_REVISION} +ENV PREFIX /opt/android/prefix + +ENV TOOLCHAIN_DIR ${WORKDIR}/toolchain +RUN set -x \ + && ${ANDROID_NDK_ROOT}/build/tools/make_standalone_toolchain.py \ + --arch x86 \ + --api 21 \ + --install-dir ${TOOLCHAIN_DIR} \ + --stl=libc++ + +#INSTALL cmake +ARG CMAKE_VERSION=3.14.6 +ARG CMAKE_HASH=82e08e50ba921035efa82b859c74c5fbe27d3e49a4003020e3c77618a4e912cd +RUN set -x \ + && cd /usr \ + && curl -L -s -O https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ + && echo "${CMAKE_HASH} cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz" | sha256sum -c \ + && tar -xzf /usr/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ + && rm -f /usr/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz +ENV PATH /usr/cmake-${CMAKE_VERSION}-Linux-x86_64/bin:$PATH + +## Boost +ARG BOOST_VERSION=1_70_0 +ARG BOOST_VERSION_DOT=1.70.0 +ARG BOOST_HASH=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 +RUN set -x \ + && curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \ + && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \ + && tar -xvf boost_${BOOST_VERSION}.tar.bz2 \ + && rm -f boost_${BOOST_VERSION}.tar.bz2 \ + && cd boost_${BOOST_VERSION} \ + && ./bootstrap.sh --prefix=${PREFIX} + +ENV HOST_PATH $PATH +ENV PATH $TOOLCHAIN_DIR/i686-linux-android/bin:$TOOLCHAIN_DIR/bin:$PATH + +ARG NPROC=1 + +# Build iconv for lib boost locale +ENV ICONV_VERSION 1.16 +ENV ICONV_HASH e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04 +RUN set -x \ + && curl -s -O http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \ + && echo "${ICONV_HASH} libiconv-${ICONV_VERSION}.tar.gz" | sha256sum -c \ + && tar -xzf libiconv-${ICONV_VERSION}.tar.gz \ + && rm -f libiconv-${ICONV_VERSION}.tar.gz \ + && cd libiconv-${ICONV_VERSION} \ + && CC=i686-linux-android-clang CXX=i686-linux-android-clang++ ./configure --build=x86_64-linux-gnu --host=i686-linux-android --prefix=${PREFIX} --disable-rpath \ + && make -j${NPROC} && make install + +## Build BOOST +RUN set -x \ + && cd boost_${BOOST_VERSION} \ + && ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --with-locale --build-dir=android --stagedir=android toolset=clang threading=multi threadapi=pthread target-os=android -sICONV_PATH=${PREFIX} install -j${NPROC} + +#Note : we build openssl because the default lacks DSA1 + +# download, configure and make Zlib +ENV ZLIB_VERSION 1.2.11 +ENV ZLIB_HASH c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 +RUN set -x \ + && curl -s -O https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \ + && echo "${ZLIB_HASH} zlib-${ZLIB_VERSION}.tar.gz" | sha256sum -c \ + && tar -xzf zlib-${ZLIB_VERSION}.tar.gz \ + && rm zlib-${ZLIB_VERSION}.tar.gz \ + && mv zlib-${ZLIB_VERSION} zlib \ + && cd zlib && CC=clang CXX=clang++ ./configure --static \ + && make -j${NPROC} + +# open ssl +ARG OPENSSL_VERSION=1.0.2p +ARG OPENSSL_HASH=50a98e07b1a89eb8f6a99477f262df71c6fa7bef77df4dc83025a2845c827d00 +RUN set -x \ + && curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ + && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \ + && tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \ + && rm openssl-${OPENSSL_VERSION}.tar.gz \ + && cd openssl-${OPENSSL_VERSION} \ + && sed -i -e "s/mandroid/target\ i686\-linux\-android/" Configure \ + && CC=clang CXX=clang++ \ + ./Configure android \ + no-asm \ + no-shared --static \ + --with-zlib-include=${WORKDIR}/zlib/include --with-zlib-lib=${WORKDIR}/zlib/lib \ + --prefix=${PREFIX} --openssldir=${PREFIX} \ + && make -j${NPROC} \ + && make install + +# ZMQ +ARG ZMQ_VERSION=v4.3.2 +ARG ZMQ_HASH=a84ffa12b2eb3569ced199660bac5ad128bff1f0 +RUN set -x \ + && git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \ + && cd libzmq \ + && test `git rev-parse HEAD` = ${ZMQ_HASH} || exit 1 \ + && ./autogen.sh \ + && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=x86-linux-android --enable-static --disable-shared \ + && make -j${NPROC} \ + && make install + +# Sodium +ARG SODIUM_VERSION=1.0.18 +ARG SODIUM_HASH=4f5e89fa84ce1d178a6765b8b46f2b6f91216677 +RUN set -x \ + && git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} \ + && cd libsodium \ + && test `git rev-parse HEAD` = ${SODIUM_HASH} || exit 1 \ + && ./autogen.sh \ + && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=x86-linux-android --enable-static --disable-shared \ + && make -j${NPROC} \ + && make install + +COPY . /src +ARG NPROC=4 +RUN set -x \ + && cd /src \ + && CMAKE_INCLUDE_PATH="${PREFIX}/include" \ + CMAKE_LIBRARY_PATH="${PREFIX}/lib" \ + ANDROID_STANDALONE_TOOLCHAIN_PATH=${TOOLCHAIN_DIR} \ + USE_SINGLE_BUILDDIR=1 \ + PATH=${HOST_PATH} make release-static-android-x86-wallet_api -j${NPROC} + +RUN set -x \ + && cd /src/build/release \ + && find . -path ./lib -prune -o -name '*.a' -exec cp '{}' lib \; diff --git a/external-libs/include/wallet2_api.h b/external-libs/include/wallet2_api.h index 99a4de7..72ff19c 100644 --- a/external-libs/include/wallet2_api.h +++ b/external-libs/include/wallet2_api.h @@ -456,6 +456,7 @@ struct Wallet //! returns both error and error string atomically. suggested to use in instead of status() and errorString() virtual void statusWithErrorString(int& status, std::string& errorString) const = 0; virtual bool setPassword(const std::string &password) = 0; + virtual const std::string& getPassword() const = 0; virtual bool setDevicePin(const std::string &pin) { (void)pin; return false; }; virtual bool setDevicePassphrase(const std::string &passphrase) { (void)passphrase; return false; }; virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0; @@ -1019,6 +1020,7 @@ struct Wallet virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const = 0; virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector &unknown_parameters, std::string &error) = 0; + virtual std::string make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const = 0; virtual std::string getDefaultDataDir() const = 0; diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3c4101c..29e4134 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists