Merge tag 'v2.1.1' into feature-v0.10

merge-requests/5/head
wow nero 3 years ago
commit ec2057cf9c
No known key found for this signature in database
GPG Key ID: 4386E69AF260078D

@ -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

@ -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 {

@ -3,6 +3,7 @@
package="com.m2049r.xmrwallet">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />

@ -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<Monero::Wallet>(env, instance);
Java_com_m2049r_xmrwallet_model_Wallet_rescanBlockchainAsyncJ(JNIEnv *env, jobject instance) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
wallet->rescanBlockchainAsync();
}

@ -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);

@ -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<String> spinnerAdapter = new ArrayAdapter<>(Objects.requireNonNull(getContext()), R.layout.item_spinner_balance, currencies);
ArrayAdapter<String> 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<TransactionInfo> 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);

@ -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);

@ -90,7 +90,6 @@ public class SendBtcAmountWizardFragment extends SendWizardFragment {
return view;
}
@Override
public boolean onValidateFields() {
Timber.i(maxBtc + "/" + minBtc);

@ -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<RequestQuote> callback = new ShiftCallback<RequestQuote>() {
@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;

@ -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<TransactionInfoAdapter.ViewHolder> {
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<TransactionInfo
DATETIME_FORMATTER.setTimeZone(tz);
}
public boolean needsTransactionUpdateOnNewBlock() {
return (infoItems.size() > 0) && !infoItems.get(0).isConfirmed();
}
private static class TransactionInfoDiff extends DiffCallback<TransactionInfo> {
public TransactionInfoDiff(List<TransactionInfo> oldList, List<TransactionInfo> newList) {
@ -95,6 +100,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
return (oldItem.direction == newItem.direction)
&& (oldItem.isPending == newItem.isPending)
&& (oldItem.isFailed == newItem.isFailed)
&& ((oldItem.confirmations == newItem.confirmations) || (oldItem.isConfirmed()))
&& (oldItem.subaddressLabel.equals(newItem.subaddressLabel))
&& (Objects.equals(oldItem.notes, newItem.notes));
}
@ -149,6 +155,8 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
final TextView tvFee;
final TextView tvPaymentId;
final TextView tvDateTime;
final CircularProgressIndicator pbConfirmations;
final TextView tvConfirmations;
TransactionInfo infoItem;
ViewHolder(View itemView) {
@ -158,6 +166,9 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
tvFee = itemView.findViewById(R.id.tx_fee);
tvPaymentId = itemView.findViewById(R.id.tx_paymentid);
tvDateTime = itemView.findViewById(R.id.tx_datetime);
pbConfirmations = itemView.findViewById(R.id.pbConfirmations);
pbConfirmations.setMax(TransactionInfo.CONFIRMATION);
tvConfirmations = itemView.findViewById(R.id.tvConfirmations);
}
private String getDateTime(long time) {
@ -182,7 +193,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
ivTxType.setVisibility(View.GONE);
}
} else {
ivTxType.setVisibility(View.GONE); // gives us more space for the amount
ivTxType.setVisibility(View.GONE);
}
String displayAmount = Helper.getDisplayAmount(infoItem.amount, Helper.DISPLAY_DIGITS_INFO);
@ -205,12 +216,34 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
this.tvFee.setText(context.getString(R.string.tx_list_failed_text));
tvFee.setVisibility(View.VISIBLE);
setTxColour(failedColour);
pbConfirmations.setVisibility(View.GONE);
tvConfirmations.setVisibility(View.GONE);
} else if (infoItem.isPending) {
setTxColour(pendingColour);
pbConfirmations.setVisibility(View.GONE);
pbConfirmations.setIndeterminate(true);
pbConfirmations.setVisibility(View.VISIBLE);
tvConfirmations.setVisibility(View.GONE);
} else if (infoItem.direction == TransactionInfo.Direction.Direction_In) {
setTxColour(inboundColour);
if (!infoItem.isConfirmed()) {
pbConfirmations.setVisibility(View.VISIBLE);
final int confirmations = (int) infoItem.confirmations;
pbConfirmations.setProgressCompat(confirmations, true);
final String confCount = Integer.toString(confirmations);
tvConfirmations.setText(confCount);
if (confCount.length() == 1) // we only have space for character in the progress circle
tvConfirmations.setVisibility(View.VISIBLE);
else
tvConfirmations.setVisibility(View.GONE);
} else {
pbConfirmations.setVisibility(View.GONE);
tvConfirmations.setVisibility(View.GONE);
}
} else {
setTxColour(outboundColour);
pbConfirmations.setVisibility(View.GONE);
tvConfirmations.setVisibility(View.GONE);
}
String tag = null;

@ -43,7 +43,7 @@ public class TransactionHistory {
this.accountIndex = accountIndex;
}
public void loadNotes(Wallet wallet) {
private void loadNotes(Wallet wallet) {
for (TransactionInfo info : transactions) {
info.notes = wallet.getUserNote(info.hash);
}
@ -61,30 +61,22 @@ public class TransactionHistory {
private List<TransactionInfo> 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<TransactionInfo> transactionInfos = refreshJ();
Timber.d("refreshed %d", transactionInfos.size());
Timber.d("refresh size=%d", transactionInfos.size());
for (Iterator<TransactionInfo> 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<TransactionInfo> refreshJ();
}

@ -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<TransactionInfo> {
public static final int CONFIRMATION = 10; // blocks
@RequiredArgsConstructor
public enum Direction {
Direction_In(0),
@ -98,6 +100,10 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
this.transfers = transfers;
}
public boolean isConfirmed() {
return confirmations >= CONFIRMATION;
}
public String getDisplayLabel() {
if (subaddressLabel.isEmpty() || (Subaddress.DEFAULT_LABEL_FORMATTER.matcher(subaddressLabel).matches()))
return ("#" + addressIndex);

@ -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);

@ -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);
}
}
}

@ -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<RequestQuote> 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;
}

@ -64,8 +64,8 @@ public class SideShiftApiImpl implements SideShiftApi, ShiftApiCall {
}
@Override
public void requestQuote(final double xmrAmount, @NonNull final ShiftCallback<RequestQuote> callback) {
RequestQuoteImpl.call(this, xmrAmount, callback);
public void requestQuote(final double btcAmount, @NonNull final ShiftCallback<RequestQuote> callback) {
RequestQuoteImpl.call(this, btcAmount, callback);
}
@Override

@ -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();

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@ -19,13 +20,43 @@
android:layout_weight="9"
android:orientation="horizontal">
<ImageView
android:id="@+id/ivTxType"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_gravity="center"
android:src="@drawable/ic_xmrto_btc"
android:visibility="visible" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<ImageView
android:id="@+id/ivTxType"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_gravity="center"
android:src="@drawable/ic_xmrto_btc"
android:visibility="visible" />
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/pbConfirmations"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:indeterminate="false"
android:max="10"
android:progress="8"
android:visibility="visible"
app:indicatorInset="0dp"
app:indicatorSize="30dp"
app:trackThickness="4dp" />
<TextView
android:id="@+id/tvConfirmations"
style="@style/MoneroText.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingBottom="1dp"
android:text="8"
android:visibility="visible" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
@ -57,8 +88,8 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_weight="13"
android:gravity="start"
tools:text="0123456789abcdef" />

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:locale="en">
<string name="about_close">أغلق</string>
<string name="about_whoami">أنا مونيرويو</string>
<string name="about_version">النسخة %1$s (%2$d)</string>
<string name="credits_text"><![CDATA[
<b>الاعتمادات</b>
<br/>
m2049r, baltsar777, anhdres, keejef,
rehrar, EarlOfEgo, ErCiccione et al.
<br/><br/>
<a href="https://monerujo.io/">monerujo.io</a>
]]></string>
<string name="privacy_policy"><![CDATA[
<h1>سياسة الخصوصية</h1>
<p>
هذه الصفحة تخبرك بسياستنا بخصوص التجميع، الاستخدام، و الافصاح عن المعلومات الشخصيةالتي نستلمها من مستخدمي تطبيقنا (مونيرويو: محفظة مونيرو)
</p>
<p>باستخدامك هذا التطبيق أنت توافق تجميع و استخدام المعلومات وفقاً لهذه السياسة
</p>
<h2>البيانات المجمعة</h2>
<p> المعلومات الشخصية هي نوع من البيانات التي قد تعرف هوية شخص ما
</p>
<p> مفاتيح مونيرو و العناوين العامة مجمعة و معالجة من قبل التطبيق محليا لغرض معالجة المعاملات و هي ترسل الى شبكة مونيرو في حالة مشفرة
</p>
<p>لا يجمع التطبيق أي معلومات شخصية أخرى</p>
<p> إذا أنت تستخدم خدمة الصراف (اختياري)، مونيرويو يجلب سعر الصرف عبر api coinmarketcap.com. اطلع على سياسة الخصوصية الخاصة بهم على https://coinmarketcap.com/privacy لتفاصيل على كيف تجمع بياناتك التي في الطلب. </p>
<p> عندما تستعمل التطبيق لتدفع إلى عنوانين بيتكوين، فأنت تستعمل خدمة SideShift.ai. اطلع على سياسة الخصوصية الخاصة بهم على https://sideshift.ai للتفاصيل. يرسل مونيرويو عنوان بيتوين و المبلغ إليهم. سيأخذ أيضاً عنوان بروتوكول الإنترنت (ip) الخاص بك.</p>
<h2>صلاحيات التطبيق</h2>
<ul>
<li>الإنترنت: للإتصال بشبكة مونيرو عبر عقدة مونيرو</li>
<li>قرائة ملفات التخزين الخارجي: لقرائة ملفات المحفظة المخزنة على الجهاز</li>
<li>الكتابة إلى التخزين الخارجي: لكتابة ملفات المحفظة المخزنة على الجهاز</li>
<li>قفل الإيقاظ: لإبقاء الجهاز ياقظاً عند التزامن</li>
<li>الكاميرا: لمسح رموز الاستجابة السريعة (qr) لاستلام مونيرو</li>
</ul>
<h2>التغيرات لسياسة الخصوصية هذه</h2>
<p>. يمكن أن نحدث سياسة الخصوصية هذه من حين إلى أخرى. سنقوم بتنبيهك لأاي تغيرات بنشر سياسة الخصوصية الجديدة في التطبيق و على الموقع (www.monerujo.io)
ننصحك أن تراجع هذه السياسة بشكل دوري لأاي تغيرات
<p>آخر تحديث لسياسة الخصوصية هذه كان في 10/11/2017
</p>
<h2>تواصل معنا</h2>
<p>privacy@monerujo.io.إذا كان لديك أي سؤال عن سياستنا أو عن كيفية تجميع بياناتك و معالجتها، الرجاء إرسال بريد الكتروني إلى
</p>
]]></string>
</resources>

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:locale="en">
<string name="help_create_new"><![CDATA[
<h1>أنشئ محفظة - جديدة</h1>
<p>إذا كنت تحتاج إلى عنوان مونيرو جديد!</p>
<p>أدخل اسم محفظة و كلمة سر فريدين.
كلمة المرور مستخدمة لتأمين بيانات محفظتك على الجهاز. استخدم كلمة سر قوية - و استخدام عبارة سر أفضل.</p>
<h2>دون البذرة الذاكرية!</h2>
<p>سترى في الشاشة التالية \"البذرة الذاكرية\" ذات 25 كلمة خاصة بك. هي كل ما تحتاجه لاسترجاع محفظتك لاحقاً و الحصول على وصول كامل لمالك.
إبقائها آمنة و خاصة مهم جداً، فهي تعطي <em>أي أحد<em> وصولاً كاملاً لمالك!</p>
<p>إذا نسيت كلمة مرور محفظتك يمكنك استرجاع محفظتك باستعمال بذرة الذاكرة.</p>
<p>ليس هناك طريقة لاسترجاع البذرة الذاكرية، إذا أضعتها ضاع مالك!
أيضاً، لا يمكن لبذرة الذاكرية أن تتغير و إذا ما سرقت أو انفضحت،
عليك أن تحول مالك إلى محفظة جديدة (مع بذرة ذاكرية جديدة). لذا من
الأفضل عمل نسخ احتياطية من بذرتك بكتابتها و تخزينها في <em>أكثر<em> من
مكان آمن</p>
]]></string>
<string name="help_create_seed"><![CDATA[
<h1>أنشئ محفظة - بذرة</h1>
<p>إذا لديك عنوان مونيرو و تريد استعادة المعاملات من سلسلة الكتل!</p>
<p>أدخل اسم محفظة و كلمة سر فريدين.
كلمة المرور مستخدمة لتأمين بيانات محفظتك على الجهاز. استخدم كلمة سر قوية - و استخدام عبارة سر أفضل.</p>
<p>أدخل بذرتك في حقل \"البذرة الذاكيرة\".<p>
<p>أدخل رقم الكتلة لأول معاملة لهذا العنوان في حقل \""\. يمكنك أيضاًاستعمال تاريخ في صيغة سسسس-شش-يي. إن لم تكن متأكداً أدخل تاريخ/كتلة تقريبي(ة) <em> قبل <em> استخدامك الأول لهذا العنوان.</p>
]]></string>
<string name="help_create_ledger"><![CDATA[
<h1>أنشئ محفظة - لدجر</h1>
<p>إذا كنت تسترجع محفظتك من جهاز لدجر نانو اس.</p>
<p>مفاتيحك السرية لا تغادر جهاز لدجر، لذا تجتاج إلى توصيله كلما أردت الوصول لمحفظتك.</p>
<p>أدخل اسم محفظة و كلمة سر فريدين. كلمة المرور مستخدمة لتأمين بيانات محفظتك على جهاز الأندرويد. استخدم كلمة سر قوية - واستخدام عبارة سر أفضل.</p>
<p>أدخل رقم الكتلة لأول معاملة لهذا العنوان في حقل \""\. يمكنك أيضاًاستعمال تاريخ في صيغة سسسس-شش-يي. إن لم تكن متأكداً أدخل تاريخ/كتلة تقريبي(ة) <em> قبل <em> استخدامك الأول لهذا العنوان.</p>
]]></string>
<string name="help_create_keys"><![CDATA[
<h1>أنشئ محفظة - مفاتيح</h1>
<p>إذا كنت تسترجع محفظتك باستخدام مفاتيحك!</p>
<p>أدخل اسم محفظة و كلمة سر فريدين. كلمة المرور مستخدمة لتأمين بيانات محفظتك على جهاز الأندرويد. استخدم كلمة سر قوية - واستخدام عبارة سر أفضل.<p>
<p>أدخل عنوان مونيرو في حقل \"العنوان العام\" و عبئ \"مفتاح الرؤية\" و \"مفتاح الانفاق\".</p>
<p>أدخل رقم الكتلة لأول معاملة لهذا العنوان في حقل \""\. يمكنك أيضاًاستعمال تاريخ في صيغة سسسس-شش-يي. إن لم تكن متأكداً أدخل تاريخ/كتلة تقريبي(ة) <em> قبل <em> استخدامك الأول لهذا العنوان.</p>
]]></string>
<string name="help_create_view"><![CDATA[
<h1>أنشئ محفظة - رؤية</h1>
<p>إذا كنت تريد مراقبة المعاملات القادمة إلى المحفظة!</p>
<p>أدخل اسم محفظة و كلمة سر فريدين. كلمة المرور مستخدمة لتأمين بيانات محفظتك على جهاز الأندرويد. استخدم كلمة سر قوية - واستخدام عبارة سر أفضل.<p>
<p>أدخل عنوان مونيرو ملكك في حقل "\عنوان عام"\ و املأ \مفتاح الرؤية"\".</p>
<p>أدخل رقم الكتلة لأول معاملة لهذا العنوان في حقل \""\. يمكنك أيضاًاستعمال تاريخ في صيغة سسسس-شش-يي. إن لم تكن متأكداً أدخل تاريخ/كتلة تقريبي(ة) <em> قبل <em> استخدامك الأول لهذا العنوان.</p>
]]></string>
<string name="help_details"><![CDATA[
<h1>تفاصيل المحفظة</h1>
<h2>العنوان العام</h2>
عنوانك العام بمثابة رقم حسابك البنكي يمكنك مشاركته مع أي أحد دون خوف من خسارة مونيرو الخاص بك. يرسل الناس المونيرو إلى محفظتك باستخدام هذا العنوان.
<h2>البذرة الذاكرية</h2>
هي كل ما تحتاجه لاسترجاع محفظتك و الحصول على وصول كامل لمالك. إبقائها خاصة و آمنة مهم جداًَ، فهي تعطي <em>لي أحد<em> وصولاً كاملاً لمونيرواتك! إذا لم تكتبها في مكان آمن رجاءً افعل!
<h2>كلمة مرور استرجاع ملفات المحفظة</h2>
تأكد من تدوين كلمة المرور هذه. ستحتاج إليها إذا أعدت ضبط جهازك أو ألغيت تثبيت التطبيق.<br/>
<h3>CrAzYpass</h3>
إذا كانت كلمة المرور المعروضة هنا هي أبجدية رقمية من 52 جزء في مجموعات من 4 - تهانينا!
ملفات محفظتك مؤمنة باستخدام مفتاح 256 بت مولد باستخدام خصائص أمان جهازك
أساساً على عبارة المرور التي خترتها (عند الإنشاء أو بتغييرها). هذا يجعلها صعبة جداً للاختراق!<br/>
هذه الميزة اجبارية لكل المحافظ الجديدة.
<h3>كلمة السر القديمة</h3>
إذا ترى عبارة مرورك هنا، محفظتك ليسب بأمان استخدام CrAzYpass. لإصلاح هذا فقط اختار \"غير كلمة المرور\" من القائمة. بعد إدخالك عبارة مرور جديدة (ربما نفسها القديمة) سيولد التطبيق CrAzYpass لك و سيؤمن ملفات محفظتك به. اكتبه!
<h3>CrAzYpass محافظ</h3>
إذا احبجت في أي وقت إلى إعادة تثبيت مونيرويو (بعد إعادة ضبط هاتفك أو التبديل إلى جهاز جديد مثلاً) أو إذا أردت استخدام ملفات المحفظة جهاز مختلف أو حاسوب، فيجب عليك استعمال كلمة المرور الاسترجاعية هذه للوصول إلى محفظتك مجدداً.<br/>
بإختيارك \"غير عبارة المرور\" من القاءمة، يمكنك اختيار عبارة مرور أخرى. انتبة أن هذا سيولد كلمة مرور استرجاعية جديدة. اكتبها!
<h2>مفتاح الرؤية</h2>
يمكنك استخدام مفتاح الرؤية الخاص بك لمراقبة المعاملات القادمة لمحفظتك دون اعطاء إذن لإنفاق المال داخل محفظتك.
<h2>مفتاح الإنفاق</h2>
مفتاح الانفاق الخاص بك يسمح لأي شحص بانفاق المونيرو المتعلق بمحفظتك، لذا لا تخبر أجداً بالمفتاح. أبقه آمناً كبذرة الذاكرية.
]]></string>
<string name="help_list"><![CDATA[
<h1>قائمة المحافظ</h1>
<h2>العقدة</h2>
<p>.مونيرويو يستخدم عقدة بعيدة للاتصال بشبكة مونيرو دون الحاجة إلى تنزيل و الاحتفاظ بنسخة كاملة من سلسة الكتل. يمكنك العثور على قائمة من العقد الشائعة أو تعلم كيف تشغل عقدة خاصة بك هنا https://moneroworld.com<p>
<p>يأتي مونيرويو مع بعض العقد البعيدة المحددة مسبقاً. مونيرويو يتذكر آخر خمس عقد مستخدمة.</p>
<h2>المحافظ</h2>
<p>هنا ترى محافظك. هن موجودات في مجلد <tt>monerujo</tt> في التخزين الداخلى لجهازك.
يمكنك استعمال تطبيق مستكشف ملفات لرؤيتهن. ينبغي عليك عمل نسخ احتياطية من هذا المجلد
على أسس منتظمة لتخزين خارج جهازك في حالة انفجاره أو سرقته</p>
<p>اختر محفظة لتفتحها أو المس زر \"+\" لإنشاء واحدة جديدة. أو اختر واحدة من عمليات المحفظة:</p>
<h3>التفاصيل</h3>
<p>أظهر تفاصيل المحفظة، البذرة و المفاتيح.</p>
<h3>استلم</h3>
<p>أنشئ رمز استجابة سريعة(qr code) لاستلام المونيرو.</p>
<h3>أعد التسمية</h3>
<p>أعد تسمية المحفظة. النسخ الاحتياطية لا تعاد التسمية.</p>
<h3>نسخة احتياطية</h3>
<p>أنشئ نسخة من المحفظة في مجلد <tt>backups</tt> داخل مجلد <tt>monerujo</tt> مستبدلة النسخ السابقة هناك. </p>
<h3>أرشيف</h3>
<p>أنشئ نسخة احتياطية ثم احذف المحفظة. النسخة تبقى في مجلد <tt>backups</tt> إذا لم تعد بحاجة إلى نسخك الاحتياطية ينبغي أن تحذفهم باستعمال متصفح ملفات أو تطبيق حذف آمن.</p>
]]></string>
<string name="help_tx_details"><![CDATA[
<h1>تفاصيل المعاملة</h1>
<h2>الوجهة</h2>
هذا هو العنوان العام للمحفظة التي تريد إرسال مونيرو إليها.
<h2>معرف الدفع</h2>
يمكنك استخدام معرف دفع لتعريف السبب لارسالك مونيرو بين طرفين. هذا اختياري
و خاص. فمثلاً يسمح لشركة بتسوية معاملتك مع غرض شريته.
<h2>TX ID</h2>
هذا هو معرف معاملتك. يمكنك استخدامه لتعريف معاملتك المشوشة في مستكشف سلسلة كتل مونيرو مثل <a href="https://xmrchain.net/">https://xmrchain.net/</a>
<h2>TX KEY (مفتاح المعاملة)</h2>
هذا هو مفتاح معاملتك الخاص، أبقه آمناً فإظهاره إلى طرف ثالث يظهر أي توقيع في (حلقة/طوق/خاتم) هو الخاص بك، جاعلاً معاملاتك شفافة.
<h2>كتلة</h2>
هذه هي الكتلة التي تحتوي معاملتك.
]]></string>
<string name="help_send"><![CDATA[
<h1>أرسل</h1>
<h2>عنوان المستلم</h2>
<p>هذا هو العنوان العام للمحفظة التي تريد إرسال مونيرو إليها، يمكنك نسخه من الحافظة
، مسح رمز استجابة سريعة (QR) أو إدخاله يدوياً. تأكد من العنوان لضمان عدم الارسال إلى عنوان خطأ.</p>
<p>بالإضافة إلى عنوان مونيرو يمكنك استعمال
<ul>
<li>مفتوحة (OpenAlias) لXMR أو BTC</li>
<li>عنوان بيتكوين</li>
</u>
يرجى ملاحظة أن إرسال BTC يتم من خلال خدمة Sideshift.ai (انظر https://sideshift.ai
للتفاصيل). راجع قسم إرسال BTC أدناه.</p>
<h2>معرف الدفع</h2>
<p> يمكنك استخدام معرف دفع لتعريف السبب لارسالك مونيرو بين طرفين. هذا اختياري
و خاص. فمثلاً يسمح لشركة بتسوية معاملتك مع غرض شريته<p>
<h1>إرسال بيتكوين</h1>
<h2>SideShift.ai</h2>
<p>Sideshift.ai خدمة طرف ثالث تعمل كصرافة من مونيرو إلى بيتكوين. نستخدم API Sideshift.ai لإدراج دفع بيتكوين في مونيرويو. رجاءاً اطلع على https://sideshift.ai و قرر لنفسك إذا ما كانت جدمة تريد استخدامها. فريق مونيرويو ليس مرتبطاً بSideshift.ai ولا يمكنه مساعدتك مع خدمتهم</p>
<h2>SideShift.ai سعر صرف<h2>
<p>في شاشة \"المبلغ\" ستعرض عليك الضوابط الحالية لخدمة Sideshift.ai
هذه الضوابط تتضمن سعر الصرف الحالي بالإضافة إلى حدود BTC الدنيا و العليا. لاحظ أن هذا السعر ليس مضموناً في هذه المرحلة</p>
<h2>SideShift.ai طلب<h2>
<p>في شاشة \"أكد\" سترى طلب Sideshift.ai الفعلي. هذا الطلب صحيح لفترة محدودة
قد تلاحظ عداًَ تنازلياً على زر \"spend\". قد يكون سعر الصرف مختلفاً عن السعر الدلالي في الشاشة السابقة</p>
<h2>السري SideShift.ai مفتاح<h2>
<p>لأن مونيرويو فقط يتعامل مع جزء مونيرو من معاملتك يمكن لمفتاح Sideshift.ai السري الخاص البك أن يستعل لتتبع جزء بيتكوين من طلبك على موقع Sideshift.ai</p>
<h2>SideShift.ai عد تنازلي</h2>
<p>عند وصول العد التنازلي إلى الصفر، تحتاج إلى الحصول على سعر جديد من Sideshift.ai بالرجوع إلى الخطوة السابقة ثم العودة إلى شاشة \"أكد\"</p>
]]></string>
<string name="help_xmrto"><![CDATA[
<h1>إرسال بيتكوين</h1>
<h2>SideShift.ai</h2>
<p>Sideshift.ai خدمة طرف ثالث تعمل كصرافة من مونيرو إلى بيتكوين. نستخدم API Sideshift.ai لإدراج دفع بيتكوين في مونيرويو. رجاءاً اطلع على https://sideshift.ai و قرر لنفسك إذا ما كانت جدمة تريد استخدامها. فريق مونيرويو ليس مرتبطاً بSideshift.ai ولا يمكنه مساعدتك مع خدمتهم.</p>
<h2>SideShift.ai سعر صرف<h2>
<p>في شاشة \"المبلغ\" ستعرض عليك الضوابط الحالية لخدمة Sideshift.ai
هذه الضوابط تتضمن سعر الصرف الحالي بالإضافة إلى حدود BTC الدنيا و العليا. لاحظ أن هذا السعر ليس مضموناً في هذه المرحلة.</p>
<h2>SideShift.ai طلب<h2>
<p>في شاشة \"أكد\" سترى طلب Sideshift.ai الفعلي. هذا الطلب صحيح لفترة محدودة
قد تلاحظ عداًَ تنازلياً على زر \"spend\". قد يكون سعر الصرف مختلفاً عن السعر الدلالي في الشاشة السابقة.</p>
<h2>السري SideShift.ai مفتاح<h2>
<p>لأن مونيرويو فقط يتعامل مع جزء مونيرو من معاملتك يمكن لمفتاح Sideshift.ai السري الخاص البك أن يستعل لتتبع جزء بيتكوين من طلبك على موقع Sideshift.ai</p>
<h2>التنازلي! SideShift.ai عد</h2>
<p>عند وصول العد التنازلي إلى الصفر، تحتاج إلى الحصول على سعر جديد من Sideshift.ai بالرجوع إلى الخطوة السابقة ثم العودة إلى شاشة \"أكد\"</p>
<string name="help_wallet"><![CDATA[
<h1>المحفظة</h1>
<h2>وضع الشارع</h2>
<p>
يمكنك تفعيل/تعطيل وضع الشارع في القائمة أو أيقونة رأس غونثر. في هذا الوضع، رصيدك لا يظهر على أي شاشة لذا يمكنك استخدام محفظتك بأمان في الشارع، القهوة، أو أي مكان عام. المعاملات السابقة أيضاً مخفية. ستعرض المعاملات الجديدة لترى أنك أرسلت/استلمت موينرو.</p>
<h2>مسح</h2>
لأن مونيرو يحب إبقاء الأشياء خاصة، كل مرة تفتح محفظة موينيرويو علينا مسح سلسلة الكتل لنرى إذا ما أرسل مونيرة إلى محفظتك. أحياناً يستغرق فترةً لأنك لم تزامن منذ فترة طويلة.
<h2>الرصيد</h2>
<p><b>النجدة! رصيد محفظتي اختفى أو هو غير مؤكد!</b><br/>
لا تفزع! عندما ترسل المال من محفظتك، بعض رصيدك سيظهر مؤقتاً كغير مؤكد.
يحصل نتيجةً لكيفية تبادل مونيرو على سلسلة الكتل و كيفية عمل الفكة. إقرأ أكثر عن الفكة على https://getmonero.org/resources/moneropedia/change.html
<h2>قائمة المعاملات</h2>
<p>في محافظ الرؤية، فقط تعرض المعاملات القادمة.</p>
]]></string>
<string name="help_node"><![CDATA[
<h1>العقد</h1>
<h2>المختصر المفيد</h2>
<p>أعد تحميل قائمة العقد بالسحب للأسفل &amp; bookmark 3&#8211;5 عقد لتسمح لمونيرويو أن يختار الأفضل لك!</p>
<h2>ما هي العقد؟</h2>
<p>مونيرويو يستخدم عقدة خارجية لالتواصل بشبكة مونيرو دون الحاجة لتنزيل نسخة كاملة من سلسلة الكتل .<p>
<h2>قائمة العقد</h2>
<p>إذا القائمة فارغة، يمكنك إما إضافة العقد يدوياً أو دع مونيرويو يمسح الشبكة لك. أو كلا الأمرين. إقرأ أكثر&#8230;</p>
<p>تعرض قائمة العقد كل العقد المعروفة حالياً. إضافةً، الطابع \ الختم الزمني لأحدث كتلة معروفة لكل عقدة يظهر
تحت اسم العقدة. تظهر أيقونة تمثل سلوك استجابة العقدة (يشير إلى مستوى الاتصال المتوقع) بجانب كل عقدة.</p>
<p>أي عقدة في القائمة يمكن أن تعلم لاستعمال لاحق.
العقد التي لم تعلم ستنسى.<p>
<p>سيختار مونيرويو العقدة المعلمة الأمثل كل مرة تستعمله.
يفعل هذا بالتأكد من ارتفاع الكتلة (ما هي حداثة العقدة؟)
إضافة إلى استجابتها (ما سرعة استجابة العقدة للطلبات؟).</p>
<p>هذه القائمة مفروزة حسب هذه الخصائص، فالعقدة العليا هي التي يختارها مونيرويو الآن. سيظهر الجزء السفلى عقد بطيئة جداً أو غير متوفرة.</p>
<h2>أضف عقدة</h2>
<p>عند لمس زر "أضف عقدة" في الأسفل، سيطلب منك إدخال تفاصيل العقدة في الحوار التالى.
"العنوان" هو اسم المضيف أو عنوان IP للعقدة - هذا المدخل الإلزامي الوحيد.
أدخل "المنفذ" إذا تشتغل العقدة في منفذ غير افتراضي )18089)
يمكنك أيضاً تسمية العقدة لتتمكن من التعرف عليها بسهولة في وقت لاحق.
بعض العقد تتطلب بيانات اعتماد لاستخدامهم. أدخل اسم المستخدم و كلمة المرور المزودين في الحقول المناسبة. الآن يمكنك "اختبار" هذه الاعدادات.
ستعرض "نتائج الاختبار" ارتفاع الكتلة، وقت الاستجابة، و عنوان IP المستعمل.
قد تكون النتيجة خطأً - عادة لأن اسم المصيف المزود لا يمكن الوصول إليه في وقت معقول أو أن بيانات الاعتماد غير صحيحة.أو أن اسم المضيف/المنفذ لا يشيران إلى عقدة مونيرو حقيقية!
عند اجتياز الاختبار (لا اخطاء) - يمكنك لمس "حسناً" لحفظ و تعليم هذه العقدة</p>
<h2>ابحث عن العقد</h2>
<p>إضافةً، يمكنك مسح الشبكة للعقد. مونيرويو سيبدأ مسح الشبكة للعقد البعيدة في منفذ 18098. يبدأ بيؤال العقد المعلمة عن أنداد آخرين في شبكة مونيرو ثم يستمر بسؤالهم عن أندادهم، وهكذا. إذا لا تملك عقد معلمة (أو لا يخبروننا عن أندادهم)، مونيرويو سيتجه مباشرةً إلى عقد بذور مونيرو ضمن مونيرو. سيتوقف المسح عند العثور على 10 عقد بعيدة. </p>
]]></string>
<string name="help_uri"><![CDATA[
<h1>استخدام رابط دفع</h1>
<p>لقد بدأت مونيرويو باستخدام رابط دفق. لإرسال المال افعل التالي:</p>
<p>
1. المحفظة التي تريد الانفاق منها<br>
2. انتظر حتى تزامن المحفظة وamp; يظهر زر "أعط"<br>
3. المس زر "أعط"
</p>
<p>.ستعبأ تفاصيل الدفع. تأكد منهم ثم أكمل كأي معاملة أخرى</p>
]]></string>
<string name="help_ok">فهمت!</string> <!-- Note: "Got it" as in "I understand this" -->
</resources>

@ -0,0 +1,418 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:locale="en">
<string name="wallet_activity_name">محفظة</string>
<string name="menu_about">عن</string>
<string name="menu_privacy">سياسة الخصوصية</string>
<string name="menu_share">شارك</string>
<string name="menu_help">ساعدني</string>
<string name="menu_receive">استلم</string>
<string name="menu_rename">أعد التسمية &#8230;</string>
<string name="menu_backup">انشئ نسخة احتياطية</string>
<string name="menu_changepw">غير كلمة المرور</string>
<string name="password_weak">&#8230; أكمل الكتابة</string>
<string name="password_fair">&#8230; مه</string>
<string name="password_good">هيا يمكنك القيام بأفضل من هذا!</string>
<string name="password_strong">تكاد تصل &#8230;</string>
<string name="password_very_strong">أجل، كالمحترفين!</string>
<string name="label_login_wallets">المحافظ</string>
<string name="label_credits">الاعتمادات</string>
<string name="label_ok">حسناً</string>
<string name="label_cancel">إلغاء</string>
<string name="label_close">أغلق</string>
<string name="label_wallet_advanced_details">المس لالتفاصيل</string>
<string name="label_send_success">نجح الإرسال</string>
<string name="label_send_done">تم</string>
<string name="label_receive_info_gen_qr_code">المس لرمز استجابة سريعة (qr)</string>
<string name="info_xmrto_enabled">دفع BTC مفعل، المس لمعلومات أكثر.</string>
<string name="info_ledger_enabled">لدجر مفعل، المس لمعلومات أكثر.</string>
<string name="info_xmrto"><![CDATA[
<b>أدخلت عنوان بيتكوين.</b><br/>
<i>سترسل XMR و سيستلم المستلم BTC باستخدام خدمة <b>Sideshift.ai</b></i>
]]></string>
<string name="info_send_xmrto_success_order_label">Sideshift.ai طلب</string>
<string name="info_send_xmrto_success_btc">%1$s BTC</string>
<string name="info_send_xmrto_paid">التأكيد معلق</string>
<string name="info_send_xmrto_unpaid">الدفع معلق</string>
<string name="info_send_xmrto_error">Sideshift.ai عطل (%1$s)</string>
<string name="info_send_xmrto_sent">BTC أرسل</string>
<string name="info_send_xmrto_query">جار الاستعلام &#8230;</string>
<string name="info_send_xmrto_parms"><![CDATA[
<b>يمكنك إرسال %1$s &#8212; %2$s BTC</b>.<br/>
<i><b>Sideshift.ai</b> يعطيك سعر صرف <b>%3$s BTC</b> <u>حالياً</u></i>.
]]></string>
<string name="send_available_btc">الرصيد: %2$s BTC (%1$s XMR)</string>
<string name="info_paymentid_integrated">&#x2714; معرف الدفع مدمج</string>
<string name="info_prepare_tx">تجهيز عمليتك</string>
<string name="label_send_progress_xmrto_create">جار إنشاء طلب Sideshift.ai</string>
<string name="label_send_progress_xmrto_query">استعلام طلب Sideshift.ai</string>
<string name="label_send_progress_create_tx">جار تجهيز معاملة مونيرو</string>
<string name="label_send_progress_queryparms">استعلام ضوابط Sideshift.ai</string>
<string name="label_generic_xmrto_error">Sideshift.ai عطل</string>
<string name="text_generic_xmrto_error">رمز: %1$d</string>
<string name="text_retry">المس لإعادة المحوالة</string>
<string name="text_noretry_monero">علقنا هنا!</string>
<string name="text_noretry">يبدو أن Sideshift.ai ليس متوفراً حالياً!</string>
<string name="text_send_btc_amount">%1$s BTC = %2$s XMR</string>
<string name="text_send_btc_rate">(الصرف: %1$s BTC/XMR)</string>
<string name="label_send_btc_xmrto_info">قم بزيارة Sideshift.ai للدعم و التتبع</string>
<string name="label_send_btc_xmrto_key_lb">المفتاح السري\nSideshift.ai</string>
<string name="label_send_btc_xmrto_key">السري Sideshift.ai مفتاح</string>
<string name="label_send_btc_address">عنوان الوجهة BTC</string>
<string name="label_send_btc_amount">المبلغ</string>
<string name="label_send_txid">معرف المعاملة</string>
<string name="label_send_address">عنوان الوجهة</string>
<string name="label_send_notes">ملاحظات</string>
<string name="backup_progress">جار إنشاء النسخة الاحتياطية</string>
<string name="archive_progress">جار الأرشفة</string>
<string name="rename_progress">جار إعادة التسمية</string>
<string name="changepw_progress">جار تغيير كلمة المرور</string>
<string name="service_progress">جار اختتام الأمور &#8230;\nقد يستغرق هذا برهةً!</string>
<string name="backup_success">نجح النسخ الاحتياطي</string>
<string name="backup_failed">فشل النسخ الاحتياطي!</string>
<string name="rename_failed">فشلت إعادة التسمية!</string>
<string name="changepw_failed">فشل تغيير كلمة السر!</string>
<string name="changepw_success">تم تغيير كلمة السر</string>
<string name="label_daemon">العقدة</string>
<string name="status_wallet_loading">جار تحميل المحفظة &#8230;</string>
<string name="status_wallet_unloaded">حفظت المحفظة</string>
<string name="status_wallet_unload_failed">فشل حفظ المحفظة!</string>
<string name="status_wallet_connecting">جار الاتصال &#8230;</string>
<string name="status_wallet_connect_failed">فشل الاتصال بالعقدة!\nتأكد من اسم المستخدم/كلمة المرور</string>
<string name="status_wallet_connect_wrongversion">نسخة العقدة غير متوافقة - حدث رجاءً!</string>
<string name="status_wallet_node_invalid">العقدة غير صحيحة!\nجرب عقدة أخرى.</string>
<string name="status_wallet_connect_ioex">لا يمكن الوصول للعقدة!\nحاول مجدداً أو جرب عقدة أخرى.</string>
<string name="status_wallet_disconnected">منقطعة</string>
<string name="status_transaction_failed">فشلت المعاملة: %1$d</string>
<string name="send_xmrto_timeout">!انتظرت طويلاً يا صاحبي!</string>
<string name="service_busy">&#8230;ما زلت مشغولاً بمحفظتك الأخيرة </string>
<string name="prompt_rename">أعد التسمية %1$s</string>
<string name="prompt_changepw">كلمة مرور جديدة ل %1$s</string>
<string name="prompt_changepwB">أعد كلمة المرور ل %1$s</string>
<string name="prompt_password">كلمة السر ل%1$s</string>
<string name="prompt_fingerprint_auth">يمكنك أيضاً فتح المحفظة باستعمال البصمة.\nرجاءً المس الحساس.</string>
<string name="prompt_open_wallet">جار فتح المحفظة&#8230;</string>
<string name="bad_fingerprint">لم يتعرف على البصمة. حاول مجدداً.</string>
<string name="bad_password">كلمة السر خاطئة!</string>
<string name="bad_saved_password">كلمة المرور المحفوظة غير صحيحة.\nرجاءً أدخل كلمة المرور يدوياً.</string>
<string name="bad_wallet">المحفظة غير موجودة!</string>
<string name="prompt_daemon_missing">!يجب ضبط العقدة!</string>
<string name="prompt_wrong_net">المحفظة لا تطابق الشبكة المختارة</string>
<string name="label_watchonly">(مشاهدة فقط)</string>
<string name="label_wallet_receive">استلم</string>
<string name="label_wallet_send">أعط</string>
<string name="xmr_unconfirmed_amount">+ %1$s XMR غير مأكد</string>
<string name="service_description">خدمة مونيرويو</string>
<string name="status_synced">تزامن؛</string>
<string name="status_remaining">الكتل التبقية</string>
<string name="status_syncing">جار مسح:</string>
<string name="message_strorage_not_writable">التخرين الخارجي غير قابل للكتابة! افزع!</string>
<string name="message_strorage_not_permitted">نحتاج إلى صلاحيات التزين الخارجي فعلاً!</string>
<string name="message_camera_not_permitted">لا كاميرا = لا مسح لرموز الاستجابة السريعة (QR)!</string>
<string name="label_copy_viewkey">مفتاح الرؤية</string>
<string name="label_copy_address">العنوان العام</string>
<string name="label_copy_xmrtokey">Sideshift.ai مفتاح</string>
<string name="message_copy_viewkey">نسخ مفتاح الرؤية إلى الحافظة!</string>
<string name="message_copy_xmrtokey">نسخ مفتاح Sideshift.ai إلى الناسخة!</string>
<string name="message_copy_address">نسخ عنوان المحفظة للحافظة!</string>
<string name="message_copy_txid">نسخ معرف المعاملة إلى الحافظة!</string>
<string name="message_nocopy">النسخ معطل لأسباب أمنية!</string>
<string name="message_exchange_failed">لا يمكن الحصول على سعر الصرف!\nاستعمل XMR/XMR أو حاول مجدداً</string>
<string name="generate_title">أنشئ محفظة</string>
<string name="generate_name_hint">اسم المحفظة</string>
<string name="generate_password_hint">كلمة مرور المحفظة</string>
<string name="generate_fingerprint_hint">اسمح لفتح المحفظة بالبصمة</string>
<string name="generate_fingerprint_warn"><![CDATA[
<strong>التوثيق بالبصمة</strong>
<p>عند تفعيل التوثيق بالبصمة، يمكنك رؤية رصيد المحفظة و استلام المال دون ادخال كلمة السر.</p>
<p>لكن لزيادة الأمان، مونيرويو سيتطلب منك أن تدخل كلمةالمرور عند رؤية تفاصيل المحفضة أو إرسال المال.</p>
<strong>تحذير أمني</strong>
<pأخيراً، نريد أن نذكرك أن أي أحد يمكنه الحصول على بصمتك سيتمكن من يطل على رصيد محفظتك.</p>
<p>مثلا، ينكن لشخص خبيث فتح محفظتك و أنت نائم.</p>
<strong> هل أنت متأكد أنك تريد تفعيل هذه ال</strong>
]]></string>
<string name="generate_bad_passwordB">السر لا تتطابق</string>
<string name="generate_empty_passwordB">لا يمكن لعبارة المرور أن تكون فارغة</string>
<string name="generate_buttonGenerate">انشئ لي محفظة و خلصنا!</string>
<string name="generate_button_accept">دونت بذرة الذاكرة</string>
<string name="generate_wallet_name">أعطني اسماً</string>
<string name="generate_wallet_exists">المحفظة موجودة!</string>
<string name="generate_wallet_dot">لا يمكن البدء ب.</string>
<string name="generate_wallet_creating">جار إنشاء المحفظة</string>
<string name="generate_wallet_created">أنشأت المحفظة</string>
<string name="generate_restoreheight_error">أدخل رقماً أو تاريخاً (سسسس-شش-يي)</string>
<string name="generate_wallet_type_key">المفاتيح</string>
<string name="generate_wallet_type_new">جديد</string>
<string name="generate_wallet_type_seed">بذرة</string>
<string name="generate_wallet_type_view">رؤية</string>
<string name="generate_address_hint">العنوان العام</string>
<string name="generate_viewkey_hint">مفتاح الرؤية</string>
<string name="generate_spendkey_hint">مفاح الإنفاق</string>
<string name="generate_mnemonic_hint">بذرة الذاكرة ذات 25 كلمة</string>
<string name="generate_restoreheight_hint">استرجع الارتفاع أو التاريخ (سسسس-شش-يي)</string>
<string name="generate_address_label">العنوان العام</string>
<string name="generate_viewkey_label">مفتاح الرؤية</string>
<string name="generate_spendkey_label">مفتاح الإنفاق</string>
<string name="generate_mnemonic_label">بذرة الذاكرة</string>
<string name="generate_crazypass_label">ملفات المحفظة استرجع كلمة المرور</string>
<string name="generate_check_key">أدخل مفتاحاً صحيحاً</string>
<string name="generate_check_address">أدخل عنواناً صحيحاً</string>
<string name="generate_check_mnemonic">أدخل بذرتك ذات 25 كلمة</string>
<string name="send_notes_hint">الملاحظات الخاصة (اختياري)</string>
<string name="send_generate_paymentid_hint">ولد</string>
<string name="send_send_label">أنفق مونيرواتي الحبيبة</string>
<string name="send_send_timed_label">أرسل مونيرواتي الحبيبة (%1$s)</string>
<string name="send_qr_invalid">ليس رمز استجابة سريعة (QR)</string>
<string name="send_qr_address_invalid">ليس رمزاً حصيحاً</string>
<string name="send_address_invalid">ليس عنواناً صحيحاً</string>
<string name="send_address_not_openalias">عنوان OpenAlias ليس متوفر</string>
<string name="send_address_openalias">آمن &#x2714;</string>
<string name="send_address_resolve_openalias">حل OpenAlias&#8230;</string>
<string name="send_address_no_dnssec">OpenAlias دون DNSSEC - قد يكون العنوان منتحل</string>
<string name="send_title">أرسل</string>
<string name="send_available">الرصيد: %1$s XMR</string>
<string name="send_address_title">العنوان</string>
<string name="send_amount_title">المبلغ</string>
<string name="send_confirm_title">أكد</string>
<string name="send_success_title">تم</string>
<string name="send_amount_label">المبلغ</string>
<string name="send_fee_btc_label">الرسوم (xmr)</string>
<string name="send_fee_label">الرسوم</string>
<string name="send_total_btc_label">المجموع (xmr)</string>
<string name="send_total_label">المجموع</string>
<string name="send_amount">%1$s XMR</string>
<string name="send_fee">+%1$s رسوم</string>
<string name="send_create_tx_error_title">عطل إنشاء المعاملة</string>
<string name="tx_list_fee">- رسوم %1$s</string>
<string name="tx_list_amount_failed">(%1$s)</string>
<string name="tx_list_failed_text">فشل</string>
<string name="tx_list_amount_negative">- %1$s</string>
<string name="tx_list_amount_positive">+ %1$s</string>
<string name="tx_timestamp">الختم الزمني</string>
<string name="tx_id">TX ID</string>
<string name="tx_key">TX Key</string>
<string name="tx_destination">الوجهة</string>
<string name="tx_paymentId">معرف الدفع</string>
<string name="tx_blockheight">الكتلة</string>
<string name="tx_amount">المبلغ</string>
<string name="tx_fee">الرسوم</string>
<string name="tx_transfers">التحويلات</string>
<string name="tx_notes">ملاحظات</string>
<string name="tx_notes_hint">(اختياري)</string>
<string name="tx_title">تفاصيل المعاملة</string>
<string name="tx_pending">معلقة</string>
<string name="tx_failed">فشلت</string>
<string name="receive_amount_hint">المبلغ</string>
<string name="receive_desc_hint">وصف (اختياري)</string>
<string name="receive_cannot_open">لم يتمكن من فتح المحفظة!</string>
<string name="receive_amount_too_big">%1$s أقصى</string>
<string name="receive_amount_negative">0 أدنى</string>
<string name="receive_amount_nan">XMR ليس رقماً</string>
<string name="details_alert_message">ستظهر بيانات حساسة.\nتفحص خلف ظهرك!</string>
<string name="details_alert_yes">أنا في أمان</string>
<string name="details_alert_no">أرجعني!</string>
<string name="details_title">التفاصيل</string>
<string name="fab_create_new">أنشئ محفظة جديدة</string>
<string name="fab_restore_viewonly">استرجع محفظة رؤية-فقط</string>
<string name="fab_restore_key">استرجع محفظة من المفاتيح الخاصة</string>
<string name="fab_restore_seed">استرجع محفظة من بذرة 25 كلمة</string>
<string name="accounts_drawer_new">أنشئ حساباً</string>
<string name="accounts_new">أضيف حساب جديد #%1$d</string>
<string name="tx_account">الحساب #</string>
<string name="send_sweepall">أرسل كل المال المؤكد في هذا الحساب!</string>
<string name="tx_subaddress">العنوان الفرعي #%1$d</string>
<string name="generate_address_label_sub">العنوان الفرعي العام #%1$d</string>
<string name="menu_language">اللغة</string>
<string name="language_system_default">استخدم لغة النظام</string>
<string name="fab_restore_ledger">استرجع من لدجر نانو اس</string>
<string name="progress_ledger_progress">جار التواصل مع اللدجر</string>
<string name="progress_ledger_confirm">التأكيد على اللدجر مطلوب!</string>
<string name="progress_ledger_lookahead">استلام العناوين الفرعية</string>
<string name="progress_ledger_verify">التأكد من صحة المفاتيح</string>
<string name="progress_ledger_opentx">القيام بحسابات مجنونة</string>
<string name="progress_ledger_mlsag">تشفير الأشياء</string>
<string name="open_wallet_ledger_missing">رجاءً (إعادة) إيصال جهاز لدجر</string>
<string name="accounts_progress_new">جار إنشاء الحساب</string>
<string name="toast_ledger_attached">%1$s اربط</string>
<string name="toast_ledger_detached">%1$s فصل</string>
<string name="progress_nfc_write">جار كتابة العلامة</string>
<string name="nfc_write_failed">فشلت كتابة العلامة</string>
<string name="nfc_write_successful">نجحت كتابة العلامة</string>
<string name="nfc_tag_unsupported">العلامة لا تدعم NDEF!</string>
<string name="nfc_tag_size">العلامة تزود %1$dلأ بايتاً، لكننا نحتاج %2$ل!</string>
<string name="nfc_tag_read_undef">لا أفهم العلامة!</string>
<string name="nfc_tag_read_what">لا أعرف ماذا تريد!</string>
<string name="nfc_tag_tap">NFC متوفر!</string>
<string name="menu_info">أظهر أسراري!</string>
<string name="menu_streetmode">وضع الشارع</string>
<string name="info_nodes_enabled">Node-o-matiC مفعل، المس لمعلومات أكثر.</string>
<string name="node_height">آخر كتلة تحدثت: %1$s</string>
<string name="label_nodes">العقد</string>
<string name="node_name_hint">اسم العقدة (اختياري)</string>
<string name="node_address_hint">اسم المضيف</string>
<string name="node_port_hint">المنفظ</string>
<string name="node_user_hint">اسم المستخدم (اختياري)</string>
<string name="node_pass_hint">كلمة المرور (اختياري)</string>
<string name="node_host_unresolved">لا يمكن حل المضيف</string>
<string name="node_host_empty">نحتاج لهذا!</string>
<string name="node_port_numeric">يجب أن يكون رقماً</string>
<string name="node_port_range">1&#8211;65535 يجب أن يكون</string>
<string name="node_fab_add">أضف عقدة</string>
<string name="node_refresh_hint">المس لإعادة التحميل</string>
<string name="node_test_error">%1$d عطل إطصال</string>
<string name="node_general_error">عطل في الاتصال</string>
<string name="node_auth_error">فشل التوثيق</string>
<string name="node_result_label">نتيجة الاختبار:</string>
<string name="node_result">الارتفاع: %1$s (v%2$d), Ping: %3$.0fms, IP: %4$s</string>
<string name="node_testing">اختبار IP: %1$s &#8230;</string>
<string name="node_refresh_wait">رجاءً انتظر انتهاء المسح</string>
<string name="node_create_hint">المس لاختيار أو إضافة العقد</string>
<string name="node_pull_hint">أضف العقد يدوياً أو اسحب للأسفل للمسح</string>
<string name="node_scanning">جار مسح الشبكة&#8230;</string>
<string name="node_nobookmark">علمت أفضل %1$d عقد تلقائياً</string>
<string name="label_test">اختبر</string><!--note: as in "Test a network connection"-->
<string name="send_address_hint">المستلم</string>
<string name="street_sweep_amount">كل شيء!</string>
<string name="menu_ledger_seed">حول بذرة اللدجر</string>
<string name="prompt_ledger_seed">كلمات بذرة اللدجر</string>
<string name="prompt_ledger_phrase">عبارة دخول اللدجر (متقدم)</string>
<string name="bad_ledger_seed">بذرة اللدجر غير صحيحة!</string>
<string name="prompt_ledger_seed_warn">إدخال بذرة اللدجر هنا خطر أمني كبير!</string>
<string name="label_restoreheight">استرجع الارتفاع</string>
<string name="toast_ledger_start_app">ابدأ تطبيق مونيرو في %1$s</string>
<string name="menu_rescan">أعد المسح!</string>
<string name="onboarding_agree">فهمت!</string>
<string name="onboarding_button_next">التالي</string>
<string name="onboarding_button_ready">أنا جاهز!</string>
<string name="onboarding_welcome_title">مرحباً بك في مونيرويو!</string>
<string name="onboarding_welcome_information">هذا التطبيق يسمح لك بإنشاء و استخدام محافظ مونيرو. يمكنك الاحتفاظ بالحبيب مونيرو فيهم.</string>
<string name="onboarding_seed_title">أبق بذرتك آمنة</string>
<string name="onboarding_seed_information">البذرة تمنح وصولاً كاملاً لمن يمتلكها.إذا ما أضعتها لا يمكننا مساعدتك في استرجاعها و ستخسر مونيرواتك الحبيبة.</string>
<string name="onboarding_xmrto_title">أرسل بيتكوين</string>
<string name="onboarding_xmrto_information">لدى مونيرويو دعم داخلي لSideshift.ai. فقط الصق أو امسح عنوان بيتكوين و سترسل بيتكون بانفاق مونيرو.</string>
<string name="onboarding_nodes_title">العقد، كما تشاء</string>
<string name="onboarding_nodes_information">العقد تصلك بشبكة مونيرو. اختر ما بين العقد العامة أو كن متمرداً سبرانياً و استخدم خاصتك.</string>
<string name="onboarding_fpsend_title">أرسل بالبصمة</string>
<string name="onboarding_fpsend_information">يمكنك الآن إرسال XMR فقط ببصمتك إذا فعلتها. لطلب كلمة المرور، فقط عطل الدخول بالبصمة.</string>
<string name="menu_daynight">الوضع الليلي</string>
<string-array name="daynight_themes">
<item>تلقائي</item>
<item>يوم</item>
<item>ليل</item>
</string-array>
<string name="gunther_says">لا شيء هنا\nالرجاء إنشاء أو استعادة محفظة</string>
<string name="menu_default_nodes">أرجع العقد الافتراضية</string>
<string name="toast_default_nodes">الاسترجاع يتقدم بالفعل...</string>
<string name="node_updated_now">الكتلة الأخيرة: منذ %1$d ثوان</string>
<string name="node_updated_mins">الكتلة الخيرة: منذ %1$d ساعة</string>
<string name="node_updated_hours">الكتلة الأخيرة: منذ %1$d ساعة</string>
<string name="node_updated_days">الكتلة الأخيرة: منذ %1$d أيام</string>
<string name="shift_noquote">لا يمكن الحصول على سعر</string>
<string name="shift_checkamount">تأكد من البلغ و حاول مجدداً</string>
<string name="info_xmrto_ambiguous"><![CDATA[
<b>عنوان مبهم.</b><br/>
<i>رجاء حدد النوع أعلاه. </i>
]]></string>
<string name="info_xmrto_help"><![CDATA[
<b>رجاء أدخل أو امسح عنوان %1$s</b><br/>
<i>سترسل XMR و سيتلقى المستلم %2$s باستعمال خدمة <b>SideShift.ai</b></i>
]]></string>
<string name="info_xmrto_help_xmr"><![CDATA[
<b>رجاء أدخل أو امسح عنوان مونيرو</b>
]]></string>
<string name="subbaddress_title">العناوين الفرعية</string>
<string name="subbaddress_name_hint">اسم العنوان الفرعي</string>
<string name="max_subaddress_warning">عناوين غير مستعملة كثيرة - استعمل بعضها لتتمكن من إنشاء المزيد!</string>
<string name="max_account_warning">حسابات غير مستعملة كثيرة - استعمل بعضها لتتمكن من إنشاء المزيد!</string>
<string name="subaddress_tx_label">المعاملات لهذا العنوان الفرعي:</string>
<string name="subaddress_notx_label">لا معاملات لهذا العنوان الفرعي بعد</string>
<string name="subaddress_select_label">اختر عنواناً فرعياً</string>
<string name="subaddress_details_hint">المس طويلاً للتفاصيل</string>
<string name="menu_restore">استورد محفظة</string>
<string name="restore_failed">فشل الاستيراد</string>
<string name="menu_deletecache">أعد ضبط المحفظة!</string>
<string name="deletecache_alert_message">ستتم إعادة ضبط هذه المحفظة ، وفقدان جميع البيانات خارج السلسلة (مثل الملاحظات ، وأسماء الحسابات والعناوين الفرعية ، ومفاتيح المعاملات الخاصة ، ...)! استخدم هذا فقط إذا كانت هذه المحفظة تالفة و لا تحمل!</string>
</resources>

@ -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<RequestQuote>() {
xmrToApi.requestQuote(btcAmount, new ShiftCallback<RequestQuote>() {
@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" +
"}";
}

@ -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'
}
}

@ -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 \;

@ -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 \;

@ -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<std::string> &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;

@ -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

Loading…
Cancel
Save