Rework gas fetch methods (#3360)

pull/3362/head
James Brown 8 months ago committed by GitHub
parent 1eec3f42cd
commit cc137bae8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      app/src/main/java/com/alphawallet/app/di/ToolsModule.java
  2. 22
      app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java
  3. 5
      app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java
  4. 7
      app/src/main/java/com/alphawallet/app/repository/TokenRepository.java
  5. 6
      app/src/main/java/com/alphawallet/app/repository/TransactionRepository.java
  6. 48
      app/src/main/java/com/alphawallet/app/service/GasService.java
  7. 6
      app/src/main/java/com/alphawallet/app/ui/AssetDisplayActivity.java
  8. 9
      app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java
  9. 6
      app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java
  10. 7
      app/src/main/java/com/alphawallet/app/ui/HomeActivity.java
  11. 6
      app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java
  12. 9
      app/src/main/java/com/alphawallet/app/ui/SendActivity.java
  13. 10
      app/src/main/java/com/alphawallet/app/ui/SwapActivity.java
  14. 6
      app/src/main/java/com/alphawallet/app/ui/TokenDetailActivity.java
  15. 6
      app/src/main/java/com/alphawallet/app/ui/TokenFunctionActivity.java
  16. 9
      app/src/main/java/com/alphawallet/app/ui/TransactionDetailActivity.java
  17. 8
      app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java
  18. 10
      app/src/main/java/com/alphawallet/app/ui/TransferTicketDetailActivity.java
  19. 7
      app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java
  20. 5
      app/src/main/java/com/alphawallet/app/ui/widget/entity/ActionSheetCallback.java
  21. 5
      app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java
  22. 8
      app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java
  23. 5
      app/src/main/java/com/alphawallet/app/viewmodel/SendViewModel.java
  24. 11
      app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java
  25. 5
      app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java
  26. 5
      app/src/main/java/com/alphawallet/app/viewmodel/TransactionDetailViewModel.java
  27. 8
      app/src/main/java/com/alphawallet/app/viewmodel/TransferTicketDetailViewModel.java
  28. 7
      app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java
  29. 11
      app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java
  30. 7
      app/src/main/java/com/alphawallet/app/walletconnect/TransactionDialogBuilder.java
  31. 3
      app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java
  32. 86
      app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java
  33. 9
      app/src/main/java/com/alphawallet/app/widget/TransactionDetailWidget.java
  34. 1
      app/src/main/res/values-es/strings.xml
  35. 1
      app/src/main/res/values-fr/strings.xml
  36. 1
      app/src/main/res/values-id/strings.xml
  37. 1
      app/src/main/res/values-my/strings.xml
  38. 1
      app/src/main/res/values-vi/strings.xml
  39. 1
      app/src/main/res/values-zh/strings.xml
  40. 1
      app/src/main/res/values/strings.xml
  41. 2
      app/src/test/java/com/alphawallet/app/viewmodel/HomeViewModelTest.java

@ -5,6 +5,7 @@ import android.content.Context;
import com.alphawallet.app.C;
import com.alphawallet.app.interact.WalletConnectInteract;
import com.alphawallet.app.repository.PreferenceRepositoryType;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.service.RealmManager;
import com.alphawallet.app.walletconnect.AWWalletConnectClient;
import com.google.gson.Gson;
@ -54,8 +55,8 @@ public class ToolsModule
@Singleton
@Provides
AWWalletConnectClient provideAWWalletConnectClient(@ApplicationContext Context context, WalletConnectInteract walletConnectInteract, PreferenceRepositoryType preferenceRepositoryType)
AWWalletConnectClient provideAWWalletConnectClient(@ApplicationContext Context context, WalletConnectInteract walletConnectInteract, PreferenceRepositoryType preferenceRepositoryType, GasService gasService)
{
return new AWWalletConnectClient(context, walletConnectInteract, preferenceRepositoryType);
return new AWWalletConnectClient(context, walletConnectInteract, preferenceRepositoryType, gasService);
}
}

@ -75,7 +75,6 @@ public class ERC721Token extends Token
{
private final Map<BigInteger, NFTAsset> tokenBalanceAssets;
private static final Map<String, Boolean> balanceChecks = new ConcurrentHashMap<>();
private boolean batchProcessingError;
public ERC721Token(TokenInfo tokenInfo, Map<BigInteger, NFTAsset> balanceList, BigDecimal balance, long blancaTime, String networkName, ContractType type)
{
@ -90,7 +89,6 @@ public class ERC721Token extends Token
}
setInterfaceSpec(type);
group = TokenGroup.NFT;
batchProcessingError = false;
}
@Override
@ -419,7 +417,7 @@ public class ERC721Token extends Token
//find tokenIds held
long currentBalance = balance != null ? balance.longValue() : 0;
if (EthereumNetworkBase.getBatchProcessingLimit(tokenInfo.chainId) > 0 && !batchProcessingError && currentBalance > 1) //no need to do batch query for 1
if (EthereumNetworkBase.getBatchProcessingLimit(tokenInfo.chainId) > 0 && currentBalance > 1) //no need to do batch query for 1
{
updateEnumerableBatchBalance(web3j, currentBalance, tokenIdsHeld, realm);
}
@ -457,11 +455,6 @@ public class ERC721Token extends Token
//do final call
handleEnumerableRequests(requests, tokenIdsHeld);
}
if (batchProcessingError)
{
updateEnumerableBalance(web3j, realm);
}
}
private void handleEnumerableRequests(BatchRequest requests, HashSet<BigInteger> tokenIdsHeld) throws IOException
@ -469,7 +462,7 @@ public class ERC721Token extends Token
BatchResponse responses = requests.send();
if (responses.getResponses().size() != requests.getRequests().size())
{
batchProcessingError = true;
EthereumNetworkBase.setBatchProcessingError(tokenInfo.chainId);
return;
}
@ -622,7 +615,7 @@ public class ERC721Token extends Token
private HashSet<BigInteger> checkBalances(Web3j web3j, HashSet<BigInteger> eventIds) throws IOException
{
HashSet<BigInteger> heldTokens = new HashSet<>();
if (EthereumNetworkBase.getBatchProcessingLimit(tokenInfo.chainId) > 0 && !batchProcessingError && eventIds.size() > 1) return checkBatchBalances(web3j, eventIds);
if (EthereumNetworkBase.getBatchProcessingLimit(tokenInfo.chainId) > 0 && eventIds.size() > 1) return checkBatchBalances(web3j, eventIds);
for (BigInteger tokenId : eventIds)
{
@ -659,15 +652,8 @@ public class ERC721Token extends Token
handleRequests(requests, balanceIds, heldTokens);
}
if (batchProcessingError)
{
return checkBalances(web3j, eventIds);
}
else
{
return heldTokens;
}
}
private void handleRequests(BatchRequest requests, List<BigInteger> balanceIds, HashSet<BigInteger> heldTokens) throws IOException
{
@ -675,7 +661,7 @@ public class ERC721Token extends Token
BatchResponse responses = requests.send();
if (responses.getResponses().size() != requests.getRequests().size())
{
batchProcessingError = true;
EthereumNetworkBase.setBatchProcessingError(tokenInfo.chainId);
return;
}

@ -577,6 +577,11 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy
public static final int INFURA_BATCH_LIMIT = 512;
public static final String INFURA_DOMAIN = "infura.io";
public static void setBatchProcessingError(long chainId)
{
batchProcessingLimitMap.put(chainId, 0);
}
//TODO: Refactor when we bump the version of java to allow switch on Long (Finally!!)
//Also TODO: add a test to check these batch limits of each chain we support
private static int batchProcessingLimit(long chainId)

@ -2,6 +2,7 @@ package com.alphawallet.app.repository;
import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.OKX_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID;
import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction;
import static java.util.Arrays.asList;
@ -95,7 +96,9 @@ public class TokenRepository implements TokenRepositoryType {
public static final BigInteger INTERFACE_BALANCES_721_TICKET = new BigInteger ("c84aae17", 16);
public static final BigInteger INTERFACE_SUPERRARE = new BigInteger ("5b5e139f", 16);
public static final BigInteger INTERFACE_ERC1155 = new BigInteger("d9b67a26", 16);
public static final BigInteger INTERFACE_ERC20 = new BigInteger("36372b07", 16);
public static final BigInteger INTERFACE_ERC721_ENUMERABLE = new BigInteger("780e9d63", 16);
public static final BigInteger INTERFACE_ERC404 = new BigInteger("b374afc4", 16);
private static final int NODE_COMMS_ERROR = -1;
private static final int CONTRACT_BALANCE_NULL = -2;
@ -1219,6 +1222,10 @@ public class TokenRepository implements TokenRepositoryType {
returnType = ContractType.ERC721_ENUMERABLE;
else if (getContractData(network, tokenInfo.address, supportsInterface(INTERFACE_OFFICIAL_ERC721), Boolean.TRUE))
returnType = ContractType.ERC721;
else if (getContractData(network, tokenInfo.address, supportsInterface(INTERFACE_ERC20), Boolean.TRUE))
returnType = ContractType.ERC20;
else if (getContractData(network, tokenInfo.address, supportsInterface(INTERFACE_ERC404), Boolean.TRUE))
returnType = ContractType.ERC20;
else if (getContractData(network, tokenInfo.address, supportsInterface(INTERFACE_SUPERRARE), Boolean.TRUE))
returnType = ContractType.ERC721;
else if (getContractData(network, tokenInfo.address, supportsInterface(INTERFACE_ERC1155), Boolean.TRUE))

@ -81,7 +81,7 @@ public class TransactionRepository implements TransactionRepositoryType
if (w3Tx.isLegacyTransaction())
{
return formatRawTransaction(w3Tx.getTransactionDestination().toString(), w3Tx.value, w3Tx.gasPrice, w3Tx.gasLimit, nonce,
!TextUtils.isEmpty(w3Tx.payload) ? Numeric.hexStringToByteArray(w3Tx.payload) : new byte[0]);
!TextUtils.isEmpty(w3Tx.payload) ? Numeric.hexStringToByteArray(w3Tx.payload) : new byte[0], w3Tx.isConstructor());
}
else
{
@ -252,11 +252,11 @@ public class TransactionRepository implements TransactionRepositoryType
/**
* Format a legacy transaction
*/
private RawTransaction formatRawTransaction(String toAddress, BigInteger amount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data)
private RawTransaction formatRawTransaction(String toAddress, BigInteger amount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data, boolean isConstructor)
{
String dataStr = data != null ? Numeric.toHexString(data) : "";
if (TextUtils.isEmpty(toAddress)) //This transaction is a constructor
if (isConstructor)
{
return RawTransaction.createContractTransaction(
BigInteger.valueOf(nonce),

@ -19,6 +19,7 @@ import com.alphawallet.app.entity.GasEstimate;
import com.alphawallet.app.entity.GasPriceSpread;
import com.alphawallet.app.entity.NetworkInfo;
import com.alphawallet.app.entity.SuggestEIP1559Kt;
import com.alphawallet.app.entity.TXSpeed;
import com.alphawallet.app.entity.Wallet;
import com.alphawallet.app.entity.tokens.Token;
import com.alphawallet.app.repository.EthereumNetworkBase;
@ -27,6 +28,7 @@ import com.alphawallet.app.repository.EthereumNetworkRepositoryType;
import com.alphawallet.app.repository.HttpServiceHelper;
import com.alphawallet.app.repository.KeyProvider;
import com.alphawallet.app.repository.KeyProviderFactory;
import com.alphawallet.app.repository.TokenRepository;
import com.alphawallet.app.repository.entity.Realm1559Gas;
import com.alphawallet.app.repository.entity.RealmGasSpread;
import com.alphawallet.app.web3.entity.Web3Transaction;
@ -147,7 +149,7 @@ public class GasService implements ContractGasProvider
.isDisposed();
//also update EIP1559 if required and we haven't previously determined there's no EIP1559 support
getEIP1559FeeStructure()
getEIP1559FeeStructure(currentChainId)
.map(result -> updateEIP1559Realm(result, currentChainId))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@ -217,11 +219,16 @@ public class GasService implements ContractGasProvider
}
else
{
return Single.fromCallable(() -> web3j.ethGasPrice().send())
return getNodeEstimate(currentChainId)
.map(price -> updateGasPrice(price, currentChainId, updated));
}
}
private Single<EthGasPrice> getNodeEstimate(long chainId)
{
return Single.fromCallable(() -> TokenRepository.getWeb3jService(chainId).ethGasPrice().send());
}
private Boolean updateGasPrice(EthGasPrice ethGasPrice, long chainId, boolean databaseUpdated)
{
currentGasPrice = ethGasPrice.getGasPrice();
@ -295,6 +302,37 @@ public class GasService implements ContractGasProvider
}
}
//If for whatever reason gasprice hasn't been fetched or is out of date, use a manual fetch to ensure process goes through.
public Single<EIP1559FeeOracleResult> fetchGasPrice(long chainId, boolean use1559Gas)
{
//fetch relevant average setting
if (use1559Gas)
{
return getEIP1559FeeStructure(chainId)
.map(result -> {
//select average
EIP1559FeeOracleResult standard = (result != null && result.containsKey(TXSpeed.STANDARD)) ? result.get(TXSpeed.STANDARD) : null;
if (standard != null)
{
return standard;
}
else
{
//return legacy calc
EthGasPrice gasPrice = getNodeEstimate(chainId).blockingGet();
return new EIP1559FeeOracleResult(BigInteger.ZERO, BigInteger.ZERO, gasPrice.getGasPrice());
}
});
}
else
{
//get legacy gas
return getNodeEstimate(chainId)
.map(result -> new EIP1559FeeOracleResult(result.getGasPrice(), BigInteger.ZERO, BigInteger.ZERO));
}
}
private boolean updateEIP1559Realm(final Map<Integer, EIP1559FeeOracleResult> result, final long chainId)
{
boolean succeeded = true;
@ -420,10 +458,10 @@ public class GasService implements ContractGasProvider
return Single.fromCallable(() -> web3j.ethEstimateGas(transaction).send());
}
private Single<Map<Integer, EIP1559FeeOracleResult>> getEIP1559FeeStructure()
private Single<Map<Integer, EIP1559FeeOracleResult>> getEIP1559FeeStructure(long chainId)
{
return InfuraGasAPI.get1559GasEstimates(currentChainId, httpClient)
.flatMap(result -> BlockNativeGasAPI.get(httpClient).get1559GasEstimates(result, currentChainId))
return InfuraGasAPI.get1559GasEstimates(chainId, httpClient)
.flatMap(result -> BlockNativeGasAPI.get(httpClient).get1559GasEstimates(result, chainId))
.flatMap(this::useCalculationIfRequired); //if interface doesn't have blocknative API then use calculation method
}

@ -579,4 +579,10 @@ public class AssetDisplayActivity extends BaseActivity implements StandardFuncti
{
return wallet.type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
}

@ -82,6 +82,7 @@ import com.alphawallet.app.repository.EthereumNetworkRepository;
import com.alphawallet.app.repository.TokenRepository;
import com.alphawallet.app.repository.TokensRealmSource;
import com.alphawallet.app.repository.entity.RealmToken;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.service.WalletConnectService;
import com.alphawallet.app.ui.QRScanning.QRScannerActivity;
import com.alphawallet.app.ui.widget.OnDappHomeNavClickListener;
@ -120,13 +121,13 @@ import com.alphawallet.token.entity.EthereumTypedMessage;
import com.alphawallet.token.entity.SalesOrderMalformed;
import com.alphawallet.token.entity.SignMessageType;
import com.alphawallet.token.entity.Signable;
import org.web3j.utils.Numeric;
import com.alphawallet.token.tools.ParseMagicLink;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.utils.Numeric;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -1236,6 +1237,12 @@ public class DappBrowserFragment extends BaseFragment implements OnSignTransacti
return wallet.type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
@Override
public void onSignTransaction(Web3Transaction transaction, String url)
{

@ -482,6 +482,12 @@ public class FunctionActivity extends BaseActivity implements FunctionCallback,
return tokenId;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
private void calculateEstimateDialog()
{
if (alertDialog != null && alertDialog.isShowing()) alertDialog.dismiss();

@ -64,6 +64,7 @@ import com.alphawallet.app.entity.attestation.SmartPassReturn;
import com.alphawallet.app.entity.tokens.TokenCardMeta;
import com.alphawallet.app.router.ImportTokenRouter;
import com.alphawallet.app.service.DeepLinkService;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.service.PriceAlertsService;
import com.alphawallet.app.ui.widget.entity.ActionSheetCallback;
import com.alphawallet.app.ui.widget.entity.PagerCallback;
@ -667,6 +668,12 @@ public class HomeActivity extends BaseNavigationActivity implements View.OnClick
}
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
private void showPage(WalletPage page)
{
WalletPage oldPage = WalletPage.values()[viewPager.getCurrentItem()];

@ -829,6 +829,12 @@ public class NFTAssetDetailActivity extends BaseActivity implements StandardFunc
return viewModel.getWallet().type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
@Override
public void completeFunctionSetup()
{

@ -58,9 +58,10 @@ import com.alphawallet.app.widget.SignTransactionDialog;
import com.alphawallet.hardware.SignatureFromKey;
import com.alphawallet.token.entity.SalesOrderMalformed;
import com.alphawallet.token.tools.Convert;
import org.web3j.utils.Numeric;
import com.alphawallet.token.tools.ParseMagicLink;
import org.web3j.utils.Numeric;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.SocketTimeoutException;
@ -673,6 +674,12 @@ public class SendActivity extends BaseActivity implements AmountReadyCallback, S
return wallet.type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
private void txWritten(TransactionReturn txData)
{
confirmationDialog.transactionWritten(txData.hash);

@ -33,6 +33,7 @@ import com.alphawallet.app.entity.lifi.Chain;
import com.alphawallet.app.entity.lifi.Connection;
import com.alphawallet.app.entity.lifi.Quote;
import com.alphawallet.app.entity.lifi.Token;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.ui.widget.entity.ActionSheetCallback;
import com.alphawallet.app.ui.widget.entity.ProgressInfo;
import com.alphawallet.app.util.BalanceUtils;
@ -49,9 +50,10 @@ import com.alphawallet.app.widget.TokenInfoView;
import com.alphawallet.app.widget.TokenSelector;
import com.alphawallet.ethereum.EthereumNetworkBase;
import com.alphawallet.hardware.SignatureFromKey;
import org.web3j.utils.Numeric;
import com.google.android.material.button.MaterialButton;
import org.web3j.utils.Numeric;
import java.util.ArrayList;
import java.util.List;
@ -791,4 +793,10 @@ public class SwapActivity extends BaseActivity implements StandardFunctionInterf
{
return wallet.type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
}

@ -357,4 +357,10 @@ public class TokenDetailActivity extends BaseActivity implements StandardFunctio
{
return viewModel.getWallet().type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
}

@ -494,4 +494,10 @@ public class TokenFunctionActivity extends BaseActivity implements StandardFunct
{
return viewModel.getWallet().type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
}

@ -34,6 +34,7 @@ import com.alphawallet.app.entity.analytics.ActionSheetMode;
import com.alphawallet.app.entity.tokens.Token;
import com.alphawallet.app.repository.EthereumNetworkRepository;
import com.alphawallet.app.router.HomeRouter;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.ui.widget.entity.ActionSheetCallback;
import com.alphawallet.app.ui.widget.entity.TokenTransferData;
import com.alphawallet.app.util.BalanceUtils;
@ -48,9 +49,9 @@ import com.alphawallet.app.widget.FunctionButtonBar;
import com.alphawallet.app.widget.SignTransactionDialog;
import com.alphawallet.app.widget.TokenIcon;
import com.alphawallet.hardware.SignatureFromKey;
import org.web3j.utils.Numeric;
import org.web3j.crypto.Keys;
import org.web3j.utils.Numeric;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -542,6 +543,12 @@ public class TransactionDetailActivity extends BaseActivity implements StandardF
return wallet.type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
@Override
public void notifyConfirm(String mode)
{

@ -57,9 +57,9 @@ import com.alphawallet.app.widget.ProgressView;
import com.alphawallet.app.widget.SignTransactionDialog;
import com.alphawallet.app.widget.SystemView;
import com.alphawallet.hardware.SignatureFromKey;
import org.web3j.utils.Numeric;
import org.jetbrains.annotations.NotNull;
import org.web3j.utils.Numeric;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -469,6 +469,12 @@ public class TransferNFTActivity extends BaseActivity implements TokensAdapterCa
return viewModel.getWallet().type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
private void txWritten(TransactionReturn txReturn)
{
actionDialog.transactionWritten(txReturn.hash);

@ -49,7 +49,6 @@ import com.alphawallet.app.entity.SignAuthenticationCallback;
import com.alphawallet.app.entity.StandardFunctionInterface;
import com.alphawallet.app.entity.TransactionReturn;
import com.alphawallet.app.entity.WalletType;
import com.alphawallet.hardware.SignatureFromKey;
import com.alphawallet.app.entity.tokens.ERC721Token;
import com.alphawallet.app.entity.tokens.Token;
import com.alphawallet.app.repository.EthereumNetworkBase;
@ -73,9 +72,10 @@ import com.alphawallet.app.widget.InputAddress;
import com.alphawallet.app.widget.ProgressView;
import com.alphawallet.app.widget.SignTransactionDialog;
import com.alphawallet.app.widget.SystemView;
import org.web3j.utils.Numeric;
import com.alphawallet.hardware.SignatureFromKey;
import org.jetbrains.annotations.NotNull;
import org.web3j.utils.Numeric;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -948,6 +948,12 @@ public class TransferTicketDetailActivity extends BaseActivity
return viewModel.getWallet().type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
private void txWritten(TransactionReturn transactionReturn)
{
actionDialog.transactionWritten(transactionReturn.hash);

@ -46,6 +46,7 @@ import com.alphawallet.app.entity.walletconnect.SignType;
import com.alphawallet.app.entity.walletconnect.WCRequest;
import com.alphawallet.app.repository.EthereumNetworkBase;
import com.alphawallet.app.repository.SignRecord;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.ui.widget.entity.ActionSheetCallback;
import com.alphawallet.app.viewmodel.WalletConnectViewModel;
import com.alphawallet.app.walletconnect.AWWalletConnectClient;
@ -1403,6 +1404,12 @@ public class WalletConnectActivity extends BaseActivity implements ActionSheetCa
}
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
@Override
public void denyWalletConnect()
{

@ -6,9 +6,10 @@ import androidx.activity.result.ActivityResultLauncher;
import com.alphawallet.app.entity.SignAuthenticationCallback;
import com.alphawallet.app.entity.WalletType;
import com.alphawallet.hardware.SignatureFromKey;
import com.alphawallet.app.entity.tokens.Token;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.web3.entity.Web3Transaction;
import com.alphawallet.hardware.SignatureFromKey;
import com.alphawallet.token.entity.Signable;
import java.math.BigInteger;
@ -70,4 +71,6 @@ public interface ActionSheetCallback
{
return BigInteger.ZERO;
}
GasService getGasService();
}

@ -497,4 +497,9 @@ public class DappBrowserViewModel extends BaseViewModel implements TransactionSe
tokensService.setupFilter(true);
}
public GasService getGasService()
{
return gasService;
}
}

@ -56,6 +56,7 @@ import com.alphawallet.app.router.MyAddressRouter;
import com.alphawallet.app.service.AlphaWalletNotificationService;
import com.alphawallet.app.service.AnalyticsServiceType;
import com.alphawallet.app.service.AssetDefinitionService;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.service.RealmManager;
import com.alphawallet.app.service.TokensService;
import com.alphawallet.app.service.TransactionsService;
@ -132,6 +133,7 @@ public class HomeViewModel extends BaseViewModel
private final OkHttpClient httpClient;
private final RealmManager realmManager;
private final TokensService tokensService;
private final GasService gasService;
private final AlphaWalletNotificationService alphaWalletNotificationService;
private final MutableLiveData<String> walletName = new MutableLiveData<>();
private final MutableLiveData<Wallet> defaultWallet = new MutableLiveData<>();
@ -160,7 +162,8 @@ public class HomeViewModel extends BaseViewModel
OkHttpClient httpClient,
RealmManager realmManager,
TokensService tokensService,
AlphaWalletNotificationService alphaWalletNotificationService)
AlphaWalletNotificationService alphaWalletNotificationService,
GasService gasService)
{
this.preferenceRepository = preferenceRepository;
this.importTokenRouter = importTokenRouter;
@ -179,6 +182,7 @@ public class HomeViewModel extends BaseViewModel
setAnalyticsService(analyticsService);
this.preferenceRepository.incrementLaunchCount();
this.tokensService = tokensService;
this.gasService = gasService;
}
@Override
@ -216,6 +220,8 @@ public class HomeViewModel extends BaseViewModel
return defaultWallet;
}
public GasService getGasService() { return gasService; }
public void prepare(Activity activity)
{
progress.postValue(false);

@ -189,4 +189,9 @@ public class SendViewModel extends BaseViewModel implements TransactionSendHandl
{
transactionError.postValue(txError);
}
public GasService getGasService()
{
return gasService;
}
}

@ -23,6 +23,7 @@ import com.alphawallet.app.repository.PreferenceRepositoryType;
import com.alphawallet.app.repository.SwapRepositoryType;
import com.alphawallet.app.service.AnalyticsServiceType;
import com.alphawallet.app.service.AssetDefinitionService;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.service.KeyService;
import com.alphawallet.app.service.SwapService;
import com.alphawallet.app.service.TokensService;
@ -67,6 +68,7 @@ public class SwapViewModel extends BaseViewModel implements TransactionSendHandl
private final SwapService swapService;
private final CreateTransactionInteract createTransactionInteract;
private final KeyService keyService;
private final GasService gasService;
private final MutableLiveData<List<Chain>> chains = new MutableLiveData<>();
private final MutableLiveData<Chain> chain = new MutableLiveData<>();
@ -91,7 +93,8 @@ public class SwapViewModel extends BaseViewModel implements TransactionSendHandl
SwapService swapService,
CreateTransactionInteract createTransactionInteract,
KeyService keyService,
AnalyticsServiceType analyticsService)
AnalyticsServiceType analyticsService,
GasService gasService)
{
this.assetDefinitionService = assetDefinitionService;
this.preferenceRepository = preferenceRepository;
@ -100,6 +103,7 @@ public class SwapViewModel extends BaseViewModel implements TransactionSendHandl
this.swapService = swapService;
this.createTransactionInteract = createTransactionInteract;
this.keyService = keyService;
this.gasService = gasService;
setAnalyticsService(analyticsService);
}
@ -495,4 +499,9 @@ public class SwapViewModel extends BaseViewModel implements TransactionSendHandl
{
transactionError.postValue(error);
}
public GasService getGasService()
{
return gasService;
}
}

@ -1042,4 +1042,9 @@ public class TokenFunctionViewModel extends BaseViewModel implements Transaction
TokenScriptResult.addPair(attrs, attribute);
}
}
public GasService getGasService()
{
return gasService;
}
}

@ -375,4 +375,9 @@ public class TransactionDetailViewModel extends BaseViewModel implements Transac
currentBlockUpdateDisposable.dispose();
}
}
public GasService getGasService()
{
return gasService;
}
}

@ -38,9 +38,10 @@ import com.alphawallet.hardware.SignatureFromKey;
import com.alphawallet.hardware.SignatureReturnType;
import com.alphawallet.token.entity.SalesOrderMalformed;
import com.alphawallet.token.entity.SignableBytes;
import org.web3j.utils.Numeric;
import com.alphawallet.token.tools.ParseMagicLink;
import org.web3j.utils.Numeric;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
@ -356,4 +357,9 @@ public class TransferTicketDetailViewModel extends BaseViewModel implements Tran
.findWallet(address)
.subscribe(this::onDefaultWallet, this::onError);
}
public GasService getGasService()
{
return gasService;
}
}

@ -30,7 +30,6 @@ import com.alphawallet.app.interact.FetchWalletsInteract;
import com.alphawallet.app.interact.FindDefaultNetworkInteract;
import com.alphawallet.app.interact.GenericWalletInteract;
import com.alphawallet.app.interact.WalletConnectInteract;
import com.alphawallet.app.repository.EthereumNetworkRepository;
import com.alphawallet.app.repository.EthereumNetworkRepositoryType;
import com.alphawallet.app.repository.SignRecord;
import com.alphawallet.app.repository.entity.RealmWCSession;
@ -53,6 +52,7 @@ import com.alphawallet.app.web3.entity.Web3Transaction;
import com.alphawallet.hardware.SignatureFromKey;
import com.alphawallet.token.entity.EthereumTypedMessage;
import com.alphawallet.token.entity.Signable;
import org.web3j.utils.Numeric;
import java.math.BigDecimal;
@ -170,6 +170,11 @@ public class WalletConnectViewModel extends BaseViewModel implements Transaction
.subscribe(this::onDefaultWallet, this::onError);
}
public GasService getGasService()
{
return gasService;
}
public void startGasCycle(long chainId)
{
gasService.startGasPriceCycle(chainId);

@ -31,6 +31,7 @@ import com.alphawallet.app.repository.EthereumNetworkBase;
import com.alphawallet.app.repository.KeyProvider;
import com.alphawallet.app.repository.KeyProviderFactory;
import com.alphawallet.app.repository.PreferenceRepositoryType;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.service.WalletConnectV2Service;
import com.alphawallet.app.ui.WalletConnectV2Activity;
import com.alphawallet.app.ui.widget.entity.ActionSheetCallback;
@ -76,16 +77,18 @@ public class AWWalletConnectClient implements Web3Wallet.WalletDelegate
private final MutableLiveData<List<WalletConnectSessionItem>> sessionItemMutableLiveData = new MutableLiveData<>(Collections.emptyList());
private final KeyProvider keyProvider = KeyProviderFactory.get();
private final LongSparseArray<WalletConnectV2SessionRequestHandler> requestHandlers = new LongSparseArray<>();
private final GasService gasService;
private ActionSheetCallback actionSheetCallback;
private boolean hasConnection;
private Application application;
private PreferenceRepositoryType preferenceRepository;
public AWWalletConnectClient(Context context, WalletConnectInteract walletConnectInteract, PreferenceRepositoryType preferenceRepository)
public AWWalletConnectClient(Context context, WalletConnectInteract walletConnectInteract, PreferenceRepositoryType preferenceRepository, GasService gasService)
{
this.context = context;
this.walletConnectInteract = walletConnectInteract;
this.preferenceRepository = preferenceRepository;
this.gasService = gasService;
hasConnection = false;
}
@ -513,6 +516,12 @@ public class AWWalletConnectClient implements Web3Wallet.WalletDelegate
{
}
@Override
public GasService getGasService()
{
return gasService;
}
@Override
public void dismissed(String txHash, long callbackId, boolean actionCompleted)
{

@ -24,6 +24,7 @@ import com.alphawallet.app.entity.Wallet;
import com.alphawallet.app.entity.WalletType;
import com.alphawallet.app.entity.tokens.Token;
import com.alphawallet.app.entity.walletconnect.SignType;
import com.alphawallet.app.service.GasService;
import com.alphawallet.app.ui.widget.entity.ActionSheetCallback;
import com.alphawallet.app.viewmodel.WalletConnectViewModel;
import com.alphawallet.app.walletconnect.entity.WCEthereumTransaction;
@ -113,6 +114,12 @@ public class TransactionDialogBuilder extends DialogFragment
return fromWallet.type;
}
@Override
public GasService getGasService()
{
return viewModel.getGasService();
}
@Override
public void sendTransaction(Web3Transaction tx)
{

@ -20,6 +20,7 @@ import org.web3j.protocol.core.methods.request.Transaction;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Locale;
public class Web3Transaction implements Parcelable
@ -317,7 +318,7 @@ public class Web3Transaction implements Parcelable
public boolean isConstructor()
{
return (recipient.equals(Address.EMPTY) && payload != null);
return ((TextUtils.isEmpty(recipient.toString()) || recipient.equals(Address.EMPTY)) && payload != null) && (payload.startsWith("0x6080") || payload.toLowerCase(Locale.ROOT).startsWith("0x5b6080"));
}
public boolean isBaseTransfer()

@ -19,6 +19,7 @@ import com.alphawallet.app.R;
import com.alphawallet.app.entity.ActionSheetInterface;
import com.alphawallet.app.entity.ActionSheetStatus;
import com.alphawallet.app.entity.ContractType;
import com.alphawallet.app.entity.EIP1559FeeOracleResult;
import com.alphawallet.app.entity.GasEstimate;
import com.alphawallet.app.entity.NetworkInfo;
import com.alphawallet.app.entity.SignAuthenticationCallback;
@ -52,7 +53,10 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.Nullable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import io.realm.Realm;
/**
@ -90,6 +94,10 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
private boolean use1559Transactions = false;
private Transaction transaction;
private final WalletType walletType;
@Nullable
private Disposable backupGasFetchDisposable;
private EIP1559FeeOracleResult gasToUse = null;
public ActionSheetDialog(@NonNull Activity activity, Web3Transaction tx, Token t,
String destName, String destAddress, TokensService ts,
@ -148,6 +156,9 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
gasWidgetInterface = setupGasWidget();
//ensure gas service is started
actionSheetCallback.getGasService().startGasPriceCycle(token.tokenInfo.chainId);
if (!tx.gasLimit.equals(BigInteger.ZERO))
{
setGasEstimate(new GasEstimate(tx.gasLimit));
@ -435,11 +446,6 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
public void handleClick(String action, int id)
{
//first ensure gas estimate is up to date
if (gasEstimateOutOfDate())
{
functionBar.setPrimaryButtonWaiting();
return;
}
if (walletType == WalletType.HARDWARE)
{
@ -454,14 +460,16 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
case SEND_TRANSACTION_DAPP:
case SPEEDUP_TRANSACTION:
case CANCEL_TRANSACTION:
//check gas and warn user
if (!gasWidgetInterface.checkSufficientGas())
gasToUse = getGasSettingsToUse();
if (gasToUse == null)
{
askUserForInsufficientGasConfirm();
functionBar.setPrimaryButtonWaiting();
//call gas collect then push tx again
callGasUpdateAndRePushTx();
}
else
{
handleTransactionOperation();
checkGasAndSend();
}
break;
case SIGN_TRANSACTION:
@ -484,6 +492,36 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
}
}
private void checkGasAndSend()
{
functionBar.setPrimaryButtonEnabled(true);
//check gas and warn user
if (!gasWidgetInterface.checkSufficientGas())
{
askUserForInsufficientGasConfirm();
}
else
{
handleTransactionOperation();
}
}
private void callGasUpdateAndRePushTx()
{
//fetch gas and then re-click
backupGasFetchDisposable = actionSheetCallback.getGasService().fetchGasPrice(token.tokenInfo.chainId, use1559Transactions)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(gasPriceStandard -> {
gasToUse = gasPriceStandard;
if (use1559Transactions && gasToUse.maxFeePerGas.equals(BigInteger.ZERO) && gasToUse.priorityFee.equals(BigInteger.ZERO))
{
use1559Transactions = false;
}
checkGasAndSend();
});
}
@Override
public void gasEstimateReady()
{
@ -496,9 +534,23 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
return actionSheetCallback.gasSelectLauncher();
}
private boolean gasEstimateOutOfDate()
private EIP1559FeeOracleResult getGasSettingsToUse()
{
return !gasWidget.gasPriceReady();
if (gasWidgetInterface != null && gasWidgetInterface.gasPriceReady())
{
if (use1559Transactions)
{
return new EIP1559FeeOracleResult(gasWidgetInterface.getGasMax(),
gasWidgetInterface.getPriorityFee(), gasWidgetInterface.getGasPrice());
}
else
{
return new EIP1559FeeOracleResult(BigInteger.ZERO,
BigInteger.ZERO, gasWidgetInterface.getGasPrice(candidateTransaction.gasPrice));
}
}
return null;
}
private BigDecimal getTransactionAmount()
@ -629,6 +681,10 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
setOnDismissListener(v -> {
actionSheetCallback.dismissed(txHash, callbackId, actionCompleted);
if (gasWidgetInterface != null) gasWidgetInterface.onDestroy();
if (backupGasFetchDisposable != null && !backupGasFetchDisposable.isDisposed())
{
backupGasFetchDisposable.dispose();
}
});
}
@ -664,14 +720,12 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
//form Web3Transaction
if (!use1559Transactions)
{
BigInteger currentGasPrice = gasWidgetInterface.getGasPrice(candidateTransaction.gasPrice); // also recalculates the transaction value
establishedTransaction = new Web3Transaction(
candidateTransaction.recipient,
candidateTransaction.contract,
candidateTransaction.sender,
gasWidgetInterface.getValue(),
currentGasPrice,
gasToUse.baseFee,
gasWidgetInterface.getGasLimit(),
gasWidgetInterface.getNonce(),
candidateTransaction.payload,
@ -685,8 +739,8 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
candidateTransaction.contract,
candidateTransaction.sender,
gasWidgetInterface.getValue(),
gasWidgetInterface.getGasMax(),
gasWidgetInterface.getPriorityFee(),
gasToUse.maxFeePerGas,
gasToUse.priorityFee,
gasWidgetInterface.getGasLimit(),
gasWidgetInterface.getNonce(),
candidateTransaction.payload,

@ -71,11 +71,20 @@ public class TransactionDetailWidget extends LinearLayout
textFunctionName.setText(displayText);
}
if (w3tx.isConstructor())
{
String constructor = getContext().getString(R.string.constructor);
textTransactionSummary.setText(constructor);
textFunctionName.setText(constructor);
}
else
{
SignatureLookupService svc = new SignatureLookupService();
disposable = svc.getFunctionName(w3tx.payload)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(this::onResult, error -> { });
}
layoutHolder.setOnClickListener(v -> {
if (layoutDetails.getVisibility() == View.GONE)

@ -995,4 +995,5 @@
<string name="override">Anular</string>
<string name="developer_override">Anulación del Desarrollador</string>
<string name="override_warning_text">Es posible que esté a punto de firmar una transacción sin saberlo, lo que podría vaciar sus fondos. Es posible que desee firmar el código de bytes como desarrollador y puede anular esta advertencia si configura el modo de desarrollador en la configuración avanzada.</string>
<string name="constructor">Constructor</string>
</resources>

@ -1009,4 +1009,5 @@
<string name="override">Passer outre</string>
<string name="developer_override">Remplacement du Développeur</string>
<string name="override_warning_text">Vous êtes peut-être sur le point de signer sans le savoir une transaction, ce qui pourrait vider vos fonds. Vous souhaiterez peut-être signer le bytecode en tant que développeur et vous pouvez ignorer cet avertissement si vous définissez le mode développeur dans les paramètres avancés.</string>
<string name="constructor">Constructor</string>
</resources>

@ -1000,4 +1000,5 @@
<string name="override">Mengesampingkan</string>
<string name="developer_override">Penggantian Pengembang</string>
<string name="override_warning_text">Anda mungkin tanpa sadar menandatangani transaksi, yang dapat mengosongkan dana Anda. Anda mungkin ingin menandatangani bytecode sebagai pengembang, dan Anda dapat mengabaikan peringatan ini jika Anda menyetel mode pengembang di Setelan lanjutan.</string>
<string name="constructor">Constructor</string>
</resources>

@ -1030,4 +1030,5 @@
<string name="override">ပဓ</string>
<string name="developer_override">Developer Override</string>
<string name="override_warning_text">သငက အခသညတစ သငမသက လကမည။ သငသညအငတစအန bytecode က လက၊ Advanced ဆကတင developer မက သငသတက ဤသတကက အစသည</string>
<string name="constructor">Constructor</string>
</resources>

@ -1009,4 +1009,5 @@
<string name="override">Ghi đè</string>
<string name="developer_override">Ghi đè Nhà phát triển</string>
<string name="override_warning_text">Bạn có thể sắp vô tình ký một giao dịch, điều này có thể khiến tiền của bạn bị rỗng. Bạn có thể muốn ký mã byte với tư cách là nhà phát triển và bạn có thể ghi đè cảnh báo này nếu bạn đặt chế độ nhà phát triển trong cài đặt Nâng cao.</string>
<string name="constructor">Constructor</string>
</resources>

@ -996,4 +996,5 @@
<string name="override">覆盖</string>
<string name="developer_override">开发者覆盖</string>
<string name="override_warning_text">您可能会在不知情的情况下签署一项交易,这可能会清空您的资金。 您可能希望以开发人员的身份对字节码进行签名,如果您在高级设置中设置开发人员模式,则可以覆盖此警告。</string>
<string name="constructor">Constructor</string>
</resources>

@ -1072,4 +1072,5 @@
<string name="override">Override</string>
<string name="developer_override">Developer Override</string>
<string name="override_warning_text">You might be about to unknowingly sign a transaction, which could empty your funds. You may want to sign bytecode as a developer, and you can override this warning if you set developer mode in Advanced settings.</string>
<string name="constructor">Constructor</string>
</resources>

@ -25,7 +25,7 @@ public class HomeViewModelTest
public void setUp() throws Exception
{
SharedPreferenceRepository sharedPreferenceRepository = new SharedPreferenceRepository(RuntimeEnvironment.getApplication());
homeViewModel = new HomeViewModel(sharedPreferenceRepository, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
homeViewModel = new HomeViewModel(sharedPreferenceRepository, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
}
@Test

Loading…
Cancel
Save