Use AccountSnapshot to avoid unnecessary network calls.

fork-5.53.8
Alex Voloshyn 2022-08-30 11:22:52 -07:00 zatwierdzone przez Greyson Parrelli
rodzic 936212e684
commit c80999839b
4 zmienionych plików z 78 dodań i 24 usunięć

Wyświetl plik

@ -56,12 +56,12 @@ final class MobileCoinTestNetConfig extends MobileCoinConfig {
ClientConfig config = new ClientConfig(); ClientConfig config = new ClientConfig();
String[] hardeningAdvisories = { "INTEL-SA-00334", "INTEL-SA-00615" }; String[] hardeningAdvisories = { "INTEL-SA-00334", "INTEL-SA-00615" };
VerifierFactory verifierFactory = new VerifierFactory(hardeningAdvisories, VerifierFactory verifierFactory = new VerifierFactory(hardeningAdvisories,
// ~July 15, 2022 // ~August 15, 2022
new ServiceConfig( new ServiceConfig(
"4f134dcfd9c0885956f2f9af0f05c2050d8bdee2dc63b468a640670d7adeb7f8", "01746f4dd25f8623d603534425ed45833687eca2b3ba25bdd87180b9471dac28",
"8f2f3bf81f24bf493fa6d76e29e0f081815022592b1e854f95bda750aece7452", "3e9bf61f3191add7b054f0e591b62f832854606f6594fd63faef1e2aedec4021",
"685481b33f2846585f33506ab65649c98a4a6d1244989651fd0fcde904ebd82f", "92fb35d0f603ceb5eaf2988b24a41d4a4a83f8fb9cd72e67c3bc37960d864ad6",
"719ca43abbe02f507bb91ea11ff8bc900aa86363a7d7e77b8130426fc53d8684" "3d6e528ee0574ae3299915ea608b71ddd17cbe855d4f5e1c46df9b0d22b04cdb"
)); ));
config.logAdapter = new MobileCoinLogAdapter(); config.logAdapter = new MobileCoinLogAdapter();

Wyświetl plik

@ -55,12 +55,16 @@ import java.util.concurrent.TimeoutException;
public final class Wallet { public final class Wallet {
private static final String TAG = Log.tag(Wallet.class); private static final String TAG = Log.tag(Wallet.class);
private static final Object LEDGER_LOCK = new Object();
private final MobileCoinConfig mobileCoinConfig; private final MobileCoinConfig mobileCoinConfig;
private final MobileCoinClient mobileCoinClient; private final MobileCoinClient mobileCoinClient;
private final AccountKey account; private final AccountKey account;
private final MobileCoinPublicAddress publicAddress; private final MobileCoinPublicAddress publicAddress;
private AccountSnapshot cachedAccountSnapshot;
private Amount cachedMinimumTxFee;
public Wallet(@NonNull MobileCoinConfig mobileCoinConfig, @NonNull Entropy paymentsEntropy) { public Wallet(@NonNull MobileCoinConfig mobileCoinConfig, @NonNull Entropy paymentsEntropy) {
this.mobileCoinConfig = mobileCoinConfig; this.mobileCoinConfig = mobileCoinConfig;
try { try {
@ -122,6 +126,12 @@ public final class Wallet {
return getCachedLedger(); return getCachedLedger();
} }
/**
* Retrieve a user owned ledger
* @param minimumBlockIndex require the returned ledger to include all TxOuts to at least minimumBlockIndex
* @return a wrapped MobileCoin ledger that contains only TxOuts owned by the AccountKey
* or null if the requested minimumBlockIndex cannot be retrieved
*/
@WorkerThread @WorkerThread
public @Nullable MobileCoinLedgerWrapper tryGetFullLedger(@Nullable Long minimumBlockIndex) throws IOException, FogSyncException { public @Nullable MobileCoinLedgerWrapper tryGetFullLedger(@Nullable Long minimumBlockIndex) throws IOException, FogSyncException {
try { try {
@ -130,8 +140,16 @@ public final class Wallet {
long highestBlockTimeStamp = 0; long highestBlockTimeStamp = 0;
UnsignedLong highestBlockIndex = UnsignedLong.ZERO; UnsignedLong highestBlockIndex = UnsignedLong.ZERO;
final long asOfTimestamp = System.currentTimeMillis(); final long asOfTimestamp = System.currentTimeMillis();
AccountSnapshot accountSnapshot = mobileCoinClient.getAccountSnapshot(); Amount minimumTxFee;
final Amount minimumTxFee = mobileCoinClient.getOrFetchMinimumTxFee(TokenId.MOB); AccountSnapshot accountSnapshot;
synchronized (LEDGER_LOCK) {
minimumTxFee = mobileCoinClient.getOrFetchMinimumTxFee(TokenId.MOB);
accountSnapshot = mobileCoinClient.getAccountSnapshot();
cachedMinimumTxFee = minimumTxFee;
cachedAccountSnapshot = accountSnapshot;
}
if (minimumBlockIndex != null) { if (minimumBlockIndex != null) {
long snapshotBlockIndex = accountSnapshot.getBlockIndex().longValue(); long snapshotBlockIndex = accountSnapshot.getBlockIndex().longValue();
@ -213,7 +231,13 @@ public final class Wallet {
public @NonNull Money.MobileCoin getFee(@NonNull Money.MobileCoin amount) throws IOException { public @NonNull Money.MobileCoin getFee(@NonNull Money.MobileCoin amount) throws IOException {
try { try {
BigInteger picoMob = amount.requireMobileCoin().toPicoMobBigInteger(); BigInteger picoMob = amount.requireMobileCoin().toPicoMobBigInteger();
AccountSnapshot accountSnapshot = getCachedAccountSnapshot();
Amount minimumFee = getCachedMinimumTxFee();
if (accountSnapshot != null && minimumFee != null) {
return Money.picoMobileCoin(accountSnapshot.estimateTotalFee(Amount.ofMOB(picoMob), minimumFee).getValue());
} else {
return Money.picoMobileCoin(mobileCoinClient.estimateTotalFee(Amount.ofMOB(picoMob)).getValue()); return Money.picoMobileCoin(mobileCoinClient.estimateTotalFee(Amount.ofMOB(picoMob)).getValue());
}
} catch (InvalidFogResponse | AttestationException | InsufficientFundsException e) { } catch (InvalidFogResponse | AttestationException | InsufficientFundsException e) {
Log.w(TAG, "Failed to get fee", e); Log.w(TAG, "Failed to get fee", e);
return Money.MobileCoin.ZERO; return Money.MobileCoin.ZERO;
@ -238,9 +262,7 @@ public final class Wallet {
try { try {
PaymentTransactionId.MobileCoin mobcoinTransaction = (PaymentTransactionId.MobileCoin) transactionId; PaymentTransactionId.MobileCoin mobcoinTransaction = (PaymentTransactionId.MobileCoin) transactionId;
Transaction transaction = Transaction.fromBytes(mobcoinTransaction.getTransaction()); Transaction transaction = Transaction.fromBytes(mobcoinTransaction.getTransaction());
Transaction.Status status = mobileCoinClient.getAccountSnapshot() Transaction.Status status = mobileCoinClient.getTransactionStatusQuick(transaction);
.getTransactionStatus(transaction);
switch (status) { switch (status) {
case UNKNOWN: case UNKNOWN:
Log.w(TAG, "Unknown sent Transaction Status"); Log.w(TAG, "Unknown sent Transaction Status");
@ -252,10 +274,10 @@ public final class Wallet {
default: default:
throw new IllegalStateException("Unknown Transaction Status: " + status); throw new IllegalStateException("Unknown Transaction Status: " + status);
} }
} catch (SerializationException | InvalidFogResponse e) { } catch (SerializationException e) {
Log.w(TAG, e); Log.w(TAG, e);
return TransactionStatusResult.failed(); return TransactionStatusResult.failed();
} catch (NetworkException | AttestationException e) { } catch (NetworkException e) {
Log.w(TAG, e); Log.w(TAG, e);
throw new IOException(e); throw new IOException(e);
} }
@ -324,10 +346,18 @@ public final class Wallet {
} }
try { try {
AccountSnapshot accountSnapshot = getCachedAccountSnapshot();
if (accountSnapshot != null) {
pendingTransaction = accountSnapshot.prepareTransaction(to.getAddress(),
Amount.ofMOB(picoMob),
Amount.ofMOB(feeMobileCoin.toPicoMobBigInteger()),
TxOutMemoBuilder.createSenderAndDestinationRTHMemoBuilder(account));
} else {
pendingTransaction = mobileCoinClient.prepareTransaction(to.getAddress(), pendingTransaction = mobileCoinClient.prepareTransaction(to.getAddress(),
Amount.ofMOB(picoMob), Amount.ofMOB(picoMob),
Amount.ofMOB(feeMobileCoin.toPicoMobBigInteger()), Amount.ofMOB(feeMobileCoin.toPicoMobBigInteger()),
TxOutMemoBuilder.createSenderAndDestinationRTHMemoBuilder(account)); TxOutMemoBuilder.createSenderAndDestinationRTHMemoBuilder(account));
}
} catch (InsufficientFundsException e) { } catch (InsufficientFundsException e) {
Log.w(TAG, "Insufficient funds", e); Log.w(TAG, "Insufficient funds", e);
results.add(TransactionSubmissionResult.failure(TransactionSubmissionResult.ErrorCode.INSUFFICIENT_FUNDS, false)); results.add(TransactionSubmissionResult.failure(TransactionSubmissionResult.ErrorCode.INSUFFICIENT_FUNDS, false));
@ -408,6 +438,30 @@ public final class Wallet {
getFullLedger(); getFullLedger();
} }
/**
* @return cached account snapshot or null if it's not available
* @apiNote This method is synchronized with {@link #tryGetFullLedger}
* to wait for an updated value if ledger update is in progress.
*/
@WorkerThread
private @Nullable AccountSnapshot getCachedAccountSnapshot() {
synchronized (LEDGER_LOCK) {
return cachedAccountSnapshot;
}
}
/**
* @return cached minimum transaction fee or null if it's not available
* @apiNote This method is synchronized with {@link #tryGetFullLedger}
* to wait for an updated value if ledger update is in progress.
*/
@WorkerThread
private @Nullable Amount getCachedMinimumTxFee() {
synchronized (LEDGER_LOCK) {
return cachedMinimumTxFee;
}
}
public enum TransactionStatus { public enum TransactionStatus {
COMPLETE, COMPLETE,
IN_PROGRESS, IN_PROGRESS,

Wyświetl plik

@ -93,7 +93,7 @@ dependencyResolutionManagement {
alias('rxjava3-rxkotlin').to('io.reactivex.rxjava3:rxkotlin:3.0.1') alias('rxjava3-rxkotlin').to('io.reactivex.rxjava3:rxkotlin:3.0.1')
alias('rxdogtag').to('com.uber.rxdogtag2:rxdogtag:2.0.1') alias('rxdogtag').to('com.uber.rxdogtag2:rxdogtag:2.0.1')
alias('conscrypt-android').to('org.conscrypt:conscrypt-android:2.0.0') alias('conscrypt-android').to('org.conscrypt:conscrypt-android:2.0.0')
alias('mobilecoin').to('com.mobilecoin:android-sdk:1.2.2.2') alias('mobilecoin').to('com.mobilecoin:android-sdk:1.2.2.4')
alias('leolin-shortcutbadger').to('me.leolin:ShortcutBadger:1.1.22') alias('leolin-shortcutbadger').to('me.leolin:ShortcutBadger:1.1.22')
alias('emilsjolander-stickylistheaders').to('se.emilsjolander:stickylistheaders:2.7.0') alias('emilsjolander-stickylistheaders').to('se.emilsjolander:stickylistheaders:2.7.0')
alias('jpardogo-materialtabstrip').to('com.jpardogo.materialtabstrip:library:1.0.9') alias('jpardogo-materialtabstrip').to('com.jpardogo.materialtabstrip:library:1.0.9')

Wyświetl plik

@ -1983,9 +1983,9 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="7f61d95d2616b0a39dc7449419102534f550d173f0721a3876546b7bdc746d34" origin="Generated by Gradle"/> <sha256 value="7f61d95d2616b0a39dc7449419102534f550d173f0721a3876546b7bdc746d34" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="com.mobilecoin" name="android-sdk" version="1.2.2.2"> <component group="com.mobilecoin" name="android-sdk" version="1.2.2.4">
<artifact name="android-sdk-1.2.2.2.aar"> <artifact name="android-sdk-1.2.2.4.aar">
<sha256 value="307be90acd16a9883532288722de610cfdd97ce3e2a1ee2bf64856140561a348" origin="Generated by Gradle"/> <sha256 value="82b53ddde2617cbc5402a5b52eb02bc9eff31f6e2c4b535ad8680a8f8b527fb9" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="com.pinterest" name="ktlint" version="0.43.2"> <component group="com.pinterest" name="ktlint" version="0.43.2">