diff --git a/app/src/androidTest/java/com/alphawallet/app/RPCNodesTest.java b/app/src/androidTest/java/com/alphawallet/app/RPCNodesTest.java new file mode 100644 index 0000000000..59217e72ac --- /dev/null +++ b/app/src/androidTest/java/com/alphawallet/app/RPCNodesTest.java @@ -0,0 +1,39 @@ +package com.alphawallet.app; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static com.alphawallet.app.steps.Steps.createNewWallet; +import static com.alphawallet.app.steps.Steps.gotoSettingsPage; +import static com.alphawallet.app.steps.Steps.selectMenu; +import static com.alphawallet.app.steps.Steps.selectTestNet; +import static com.alphawallet.app.util.Helper.click; +import static com.alphawallet.app.util.Helper.hasBackgroundResource; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.core.IsNot.not; + +import com.alphawallet.app.util.Helper; + +import org.junit.Test; + +public class RPCNodesTest extends BaseE2ETest +{ + + @Test + public void should_select_network() + { + createNewWallet(); + selectTestNet("Mumbai"); + + gotoSettingsPage(); + selectMenu("Select Active Networks"); + Helper.wait(1); + click(withId(R.id.action_node_status)); + Helper.wait(20); + + onView(withId(R.id.main_list)).check(matches(not(hasDescendant(allOf(withId(R.id.image_status), hasBackgroundResource(R.drawable.ic_node_not_responding)))))); + onView(withId(R.id.test_list)).check(matches(not(hasDescendant(allOf(withId(R.id.image_status), hasBackgroundResource(R.drawable.ic_node_not_responding)))))); + } + +} diff --git a/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java b/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java index 643175c8e9..de9ba0012b 100644 --- a/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java +++ b/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java @@ -6,8 +6,10 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withParent; import static androidx.test.espresso.matcher.ViewMatchers.withSubstring; +import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.alphawallet.app.util.Helper.waitUntil; +import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.not; import static org.hamcrest.core.IsInstanceOf.instanceOf; @@ -30,6 +32,11 @@ public static void shouldNotSee(String text) onView(isRoot()).perform(waitUntil(not(withSubstring(text)), TIMEOUT_IN_SECONDS)); } + public static void shouldNotSeeTag(int tagId) + { + onView(isRoot()).perform(waitUntil(not(withTagValue(equalTo(tagId))), TIMEOUT_IN_SECONDS)); + } + public static void shouldNotSee(int id) { onView(isRoot()).perform(waitUntil(not(withId(id)), TIMEOUT_IN_SECONDS)); diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index e8415d48c1..0308874e2c 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -118,6 +118,7 @@ public static void selectTestNet(String name) clickStaticListItem(withSubstring("Ethereum")); //deactivate eth onView(withId(R.id.network_scroller)).perform(swipeUp()); Helper.wait(1); + onView(withSubstring("Testnet")).perform(scrollToImproved()); onView(allOf(withId(R.id.switch_material), isDescendantOfA(withId(R.id.testnet_header)))).perform(ViewActions.click()); click(withText(R.string.action_enable_testnet)); diff --git a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java index 8efaaacd3b..7cb241363a 100644 --- a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java +++ b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java @@ -14,19 +14,24 @@ import static org.hamcrest.core.AllOf.allOf; import android.content.Context; +import android.graphics.drawable.Drawable; import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.InputMethodManager; +import android.widget.ImageView; +import androidx.core.content.ContextCompat; import androidx.test.espresso.PerformException; import androidx.test.espresso.UiController; import androidx.test.espresso.ViewAction; import androidx.test.espresso.action.ViewActions; +import androidx.test.espresso.matcher.BoundedMatcher; import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.espresso.util.HumanReadables; import androidx.test.espresso.util.TreeIterables; +import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.Matchers; @@ -215,7 +220,7 @@ public static void clickListItem(int list, Matcher matcher) { try { - click(matcher, 0); + click(matcher, 1); return; } catch (Exception e) @@ -229,11 +234,11 @@ public static void clickListItem(int list, Matcher matcher) //This is an item inside a list that doesn't scroll (eg TestNet / Mainnet list) public static void clickStaticListItem(Matcher matcher) { - for (int i = 0; i < 50; i++) + for (int i = 0; i < 49; i++) { try { - click(matcher, 0); + click(matcher, 1); return; } catch (Exception e) @@ -350,4 +355,22 @@ public static boolean hasView(String text) return false; } + + public static Matcher hasBackgroundResource(final int resourceId) { + return new BoundedMatcher<>(ImageView.class) + { + @Override + protected boolean matchesSafely(ImageView imageView) + { + Drawable expectedDrawable = ContextCompat.getDrawable(imageView.getContext(), resourceId); + return expectedDrawable != null && imageView.getBackground().getConstantState().equals(expectedDrawable.getConstantState()); + } + + @Override + public void describeTo(Description description) + { + description.appendText("has background resource with id " + resourceId); + } + }; + } } diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 09fcfe49c6..d0bcf17c22 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -24,8 +24,6 @@ public abstract class C { public static final String CLASSIC_NETWORK_NAME = "Ethereum Classic"; public static final String XDAI_NETWORK_NAME = "Gnosis"; public static final String GOERLI_NETWORK_NAME = "Görli (Test)"; - public static final String ARTIS_SIGMA1_NETWORK = "ARTIS sigma1"; - public static final String ARTIS_TAU1_NETWORK = "ARTIS tau1 (Test)"; public static final String BINANCE_TEST_NETWORK = "BSC TestNet"; public static final String BINANCE_MAIN_NETWORK = "Binance (BSC)"; public static final String HECO_MAIN_NETWORK = "Heco"; @@ -58,7 +56,6 @@ public abstract class C { public static final String ETHEREUM_TICKER_NAME = "ethereum"; public static final String CLASSIC_TICKER_NAME = "ethereum-classic"; public static final String XDAI_TICKER_NAME = "dai"; - public static final String ARTIS_SIGMA_TICKER = "artis"; public static final String BINANCE_TICKER = "binance"; public static final String ETHEREUM_TICKER = "ethereum"; @@ -68,8 +65,6 @@ public abstract class C { public static final String xDAI_SYMBOL = "xDai"; public static final String ETC_SYMBOL = "ETC"; public static final String GOERLI_SYMBOL = "GÖETH"; - public static final String ARTIS_SIGMA1_SYMBOL = "ATS"; - public static final String ARTIS_TAU1_SYMBOL = "ATS"; public static final String BINANCE_SYMBOL = "BNB"; public static final String HECO_SYMBOL = "HT"; public static final String FANTOM_SYMBOL = "FTM"; diff --git a/app/src/main/java/com/alphawallet/app/entity/EventSync.java b/app/src/main/java/com/alphawallet/app/entity/EventSync.java index 720e929d67..2e7185a098 100644 --- a/app/src/main/java/com/alphawallet/app/entity/EventSync.java +++ b/app/src/main/java/com/alphawallet/app/entity/EventSync.java @@ -648,12 +648,12 @@ private void storeTransferData(Realm instance, String hash, String valueList, St if (activityName.equals("receive")) { instance.where(RealmTransfer.class) - .equalTo("hash", hash) + .like("hash", RealmTransfer.databaseKey(token.tokenInfo.chainId, hash)) .findAll().deleteAllFromRealm(); } RealmTransfer matchingEntry = instance.where(RealmTransfer.class) - .equalTo("hash", hash) + .equalTo("hash", RealmTransfer.databaseKey(token.tokenInfo.chainId, hash)) .equalTo("tokenAddress", token.tokenInfo.address) .equalTo("eventName", activityName) .equalTo("transferDetail", valueList) @@ -662,7 +662,7 @@ private void storeTransferData(Realm instance, String hash, String valueList, St if (matchingEntry == null) //prevent duplicates { matchingEntry = instance.createObject(RealmTransfer.class); - matchingEntry.setHash(hash); + matchingEntry.setHashKey(token.tokenInfo.chainId, hash); matchingEntry.setTokenAddress(token.tokenInfo.address); } diff --git a/app/src/main/java/com/alphawallet/app/interact/FetchTransactionsInteract.java b/app/src/main/java/com/alphawallet/app/interact/FetchTransactionsInteract.java index f4aa6c8e0e..5b2bff177e 100644 --- a/app/src/main/java/com/alphawallet/app/interact/FetchTransactionsInteract.java +++ b/app/src/main/java/com/alphawallet/app/interact/FetchTransactionsInteract.java @@ -8,6 +8,7 @@ import com.alphawallet.app.repository.TokenRepositoryType; import com.alphawallet.app.repository.TransactionRepositoryType; +import io.reactivex.Completable; import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; @@ -71,4 +72,9 @@ public void restartTransactionService() { transactionRepository.restartService(); } + + public Single fetchFromNode(String walletAddress, long chainId, String hash) + { + return transactionRepository.fetchTransactionFromNode(walletAddress, chainId, hash); + } } diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 00bc978878..90dbe3af33 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -10,8 +10,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_SIGMA1_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_TAU1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_MAINNET_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_TESTNET_ID; @@ -157,8 +155,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy //See the declaration of NetworkInfo - it has a member backupNodeUrl. Put your secondary node here. public static final String CLASSIC_RPC_URL = "https://www.ethercluster.com/etc"; - public static final String ARTIS_SIGMA1_RPC_URL = "https://rpc.sigma1.artis.network"; - public static final String ARTIS_TAU1_RPC_URL = "https://rpc.tau1.artis.network"; public static final String BINANCE_TEST_RPC_URL = "https://data-seed-prebsc-1-s3.binance.org:8545"; public static final String BINANCE_TEST_FALLBACK_RPC_URL = "https://data-seed-prebsc-2-s1.binance.org:8545"; public static final String BINANCE_MAIN_RPC_URL = "https://bsc-dataseed.binance.org"; @@ -177,12 +173,12 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy //If your wallet prioritises xDai for example, you may want to move the XDAI_ID to the front of this list, //Then xDai would appear as the first token at the top of the wallet private static final List hasValue = new ArrayList<>(Arrays.asList( - MAINNET_ID, GNOSIS_ID, POLYGON_ID, CLASSIC_ID, ARTIS_SIGMA1_ID, BINANCE_MAIN_ID, HECO_ID, AVALANCHE_ID, + MAINNET_ID, GNOSIS_ID, POLYGON_ID, CLASSIC_ID, BINANCE_MAIN_ID, HECO_ID, AVALANCHE_ID, FANTOM_ID, OPTIMISTIC_MAIN_ID, CRONOS_MAIN_ID, ARBITRUM_MAIN_ID, PALM_ID, KLAYTN_ID, IOTEX_MAINNET_ID, AURORA_MAINNET_ID, MILKOMEDA_C1_ID, OKX_ID)); private static final List testnetList = new ArrayList<>(Arrays.asList( GOERLI_ID, BINANCE_TEST_ID, HECO_TEST_ID, CRONOS_TEST_ID, OPTIMISM_GOERLI_TEST_ID, ARBITRUM_GOERLI_TEST_ID, KLAYTN_BAOBAB_ID, - FANTOM_TEST_ID, IOTEX_TESTNET_ID, FUJI_TEST_ID, POLYGON_TEST_ID, MILKOMEDA_C1_TEST_ID, ARTIS_TAU1_ID, + FANTOM_TEST_ID, IOTEX_TESTNET_ID, FUJI_TEST_ID, POLYGON_TEST_ID, MILKOMEDA_C1_TEST_ID, SEPOLIA_TESTNET_ID, AURORA_TESTNET_ID, PALM_TEST_ID)); private static final List deprecatedNetworkList = new ArrayList<>(Arrays.asList( @@ -233,18 +229,10 @@ public static boolean isInfura(String rpcServerUrl) XDAI_RPC_URL, "https://blockscout.com/xdai/mainnet/tx/", GNOSIS_ID, "https://rpc.ankr.com/gnosis", "https://blockscout.com/xdai/mainnet/api?")); - put(ARTIS_SIGMA1_ID, new NetworkInfo(C.ARTIS_SIGMA1_NETWORK, C.ARTIS_SIGMA1_SYMBOL, - ARTIS_SIGMA1_RPC_URL, - "https://explorer.sigma1.artis.network/tx/", ARTIS_SIGMA1_ID, - ARTIS_SIGMA1_RPC_URL, "https://explorer.sigma1.artis.network/api?")); put(GOERLI_ID, new NetworkInfo(C.GOERLI_NETWORK_NAME, C.GOERLI_SYMBOL, GOERLI_RPC_URL, "https://goerli.etherscan.io/tx/", GOERLI_ID, GOERLI_FALLBACK_RPC_URL, "https://api-goerli.etherscan.io/api?")); - put(ARTIS_TAU1_ID, new NetworkInfo(C.ARTIS_TAU1_NETWORK, C.ARTIS_TAU1_SYMBOL, - ARTIS_TAU1_RPC_URL, - "https://explorer.tau1.artis.network/tx/", ARTIS_TAU1_ID, - ARTIS_TAU1_RPC_URL, "https://explorer.tau1.artis.network/api?")); put(BINANCE_TEST_ID, new NetworkInfo(C.BINANCE_TEST_NETWORK, C.BINANCE_SYMBOL, BINANCE_TEST_RPC_URL, "https://testnet.bscscan.com/tx/", BINANCE_TEST_ID, @@ -370,8 +358,6 @@ public static boolean isInfura(String rpcServerUrl) put(CLASSIC_ID, R.drawable.ic_icons_network_etc); //classic_logo put(GNOSIS_ID, R.drawable.ic_icons_network_gnosis); put(GOERLI_ID, R.drawable.ic_goerli); - put(ARTIS_SIGMA1_ID, R.drawable.ic_artis_sigma_logo); - put(ARTIS_TAU1_ID, R.drawable.ic_artis_tau_logo); put(BINANCE_MAIN_ID, R.drawable.ic_binance_logo); put(BINANCE_TEST_ID, R.drawable.ic_icons_tokens_bnb_testnet); put(HECO_ID, R.drawable.ic_heco_logo); @@ -410,8 +396,6 @@ public static boolean isInfura(String rpcServerUrl) put(CLASSIC_ID, R.drawable.ic_icons_network_etc); put(GNOSIS_ID, R.drawable.ic_icons_network_gnosis); put(GOERLI_ID, R.drawable.ic_goerli); - put(ARTIS_SIGMA1_ID, R.drawable.ic_icons_network_artis); - put(ARTIS_TAU1_ID, R.drawable.ic_artis_tau_logo); put(BINANCE_MAIN_ID, R.drawable.ic_icons_network_bsc); put(BINANCE_TEST_ID, R.drawable.ic_icons_tokens_bnb_testnet); put(HECO_ID, R.drawable.ic_icons_network_heco); @@ -450,8 +434,6 @@ public static boolean isInfura(String rpcServerUrl) put(CLASSIC_ID, R.color.classic); put(GNOSIS_ID, R.color.xdai); put(GOERLI_ID, R.color.goerli); - put(ARTIS_SIGMA1_ID, R.color.artis_sigma1); - put(ARTIS_TAU1_ID, R.color.artis_tau1); put(BINANCE_MAIN_ID, R.color.binance_main); put(BINANCE_TEST_ID, R.color.binance_test); put(HECO_ID, R.color.heco_main); diff --git a/app/src/main/java/com/alphawallet/app/repository/TransactionLocalSource.java b/app/src/main/java/com/alphawallet/app/repository/TransactionLocalSource.java index 562498c104..11b340e785 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TransactionLocalSource.java +++ b/app/src/main/java/com/alphawallet/app/repository/TransactionLocalSource.java @@ -12,7 +12,7 @@ public interface TransactionLocalSource { Transaction fetchTransaction(Wallet wallet, String hash); - void putTransaction(Wallet wallet, Transaction tx); + Transaction putTransaction(Wallet wallet, Transaction tx); Realm getRealmInstance(Wallet wallet); Single fetchActivityMetas(Wallet wallet, List networkFilters, long fetchTime, int fetchLimit); diff --git a/app/src/main/java/com/alphawallet/app/repository/TransactionRepository.java b/app/src/main/java/com/alphawallet/app/repository/TransactionRepository.java index 04cba5dee9..385d570e73 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TransactionRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/TransactionRepository.java @@ -231,6 +231,12 @@ public void restartService() transactionsService.startUpdateCycle(); } + public Single fetchTransactionFromNode(String walletAddress, long chainId, String hash) + { + return transactionsService.fetchTransaction(walletAddress, chainId, hash) + .map(tx -> inDiskCache.putTransaction(new Wallet(walletAddress), tx)); + } + private Single getNonceForTransaction(Web3j web3j, String wallet, long nonce) { if (nonce != -1) //use supplied nonce diff --git a/app/src/main/java/com/alphawallet/app/repository/TransactionRepositoryType.java b/app/src/main/java/com/alphawallet/app/repository/TransactionRepositoryType.java index 12aec2cde9..fb4c5a0ec1 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TransactionRepositoryType.java +++ b/app/src/main/java/com/alphawallet/app/repository/TransactionRepositoryType.java @@ -47,4 +47,6 @@ public interface TransactionRepositoryType RawTransaction formatRawTransaction(Web3Transaction w3Tx, long nonce, long chainId); Single sendTransaction(Wallet from, RawTransaction rtx, SignatureFromKey sigData, long chainId); + + Single fetchTransactionFromNode(String walletAddress, long chainId, String hash); } diff --git a/app/src/main/java/com/alphawallet/app/repository/TransactionsRealmCache.java b/app/src/main/java/com/alphawallet/app/repository/TransactionsRealmCache.java index 545c0f9160..a65504ebf8 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TransactionsRealmCache.java +++ b/app/src/main/java/com/alphawallet/app/repository/TransactionsRealmCache.java @@ -235,7 +235,7 @@ public RealmAuxData fetchEvent(String walletAddress, String eventKey) } @Override - public void putTransaction(Wallet wallet, final Transaction tx) + public Transaction putTransaction(Wallet wallet, final Transaction tx) { try (Realm instance = realmManager.getRealmInstance(wallet)) { @@ -258,6 +258,8 @@ public void putTransaction(Wallet wallet, final Transaction tx) //do not record Timber.w(e); } + + return tx; } @Override diff --git a/app/src/main/java/com/alphawallet/app/repository/entity/RealmTransfer.java b/app/src/main/java/com/alphawallet/app/repository/entity/RealmTransfer.java index f76e546076..6e5de413f1 100644 --- a/app/src/main/java/com/alphawallet/app/repository/entity/RealmTransfer.java +++ b/app/src/main/java/com/alphawallet/app/repository/entity/RealmTransfer.java @@ -14,9 +14,33 @@ public class RealmTransfer extends RealmObject public String getHash() { - return hash; + String[] split = hash.split("-"); + if (split.length > 0) + { + return split[0]; + } + else + { + return ""; + } + } + public void setHashKey(long chainId, String hash) + { + this.hash = databaseKey(chainId, hash); + } + + public long getChain() + { + String[] split = hash.split("-"); + if (split.length > 1) + { + return Long.parseLong(split[1]); + } + else + { + return 0L; + } } - public void setHash(String hash) { this.hash = hash; } public String getTokenAddress() { @@ -47,4 +71,9 @@ public void setEventName(String eventName) { this.eventName = eventName; } + + public static String databaseKey(long chainId, String hash) + { + return hash + "-" + chainId; + } } diff --git a/app/src/main/java/com/alphawallet/app/service/GasService.java b/app/src/main/java/com/alphawallet/app/service/GasService.java index 760559ec79..3919c7271d 100644 --- a/app/src/main/java/com/alphawallet/app/service/GasService.java +++ b/app/src/main/java/com/alphawallet/app/service/GasService.java @@ -7,7 +7,6 @@ import static com.alphawallet.app.entity.tokenscript.TokenscriptFunction.ZERO_ADDRESS; import static com.alphawallet.app.repository.TokenRepository.getWeb3jService; import static com.alphawallet.app.repository.TokensRealmSource.TICKER_DB; -import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_TAU1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; import android.text.TextUtils; @@ -230,22 +229,7 @@ private Boolean updateGasPrice(EthGasPrice ethGasPrice, long chainId) private BigInteger fixGasPrice(BigInteger gasPrice, long chainId) { - if (gasPrice.compareTo(BigInteger.ZERO) > 0) - { - return gasPrice; - } - else - { - //gas price from node is zero - switch ((int)chainId) - { - default: - return gasPrice; - case (int)ARTIS_TAU1_ID: - //this node incorrectly returns gas price zero, use 1 Gwei - return new BigInteger(C.DEFAULT_XDAI_GAS_PRICE); - } - } + return gasPrice; } private Single updateEtherscanGasPrices(String gasOracleAPI) diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index b045f1a4a8..f35489d6ee 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -2,7 +2,6 @@ import static com.alphawallet.app.entity.tokenscript.TokenscriptFunction.ZERO_ADDRESS; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_SIGMA1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.AVALANCHE_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_MAIN_ID; @@ -142,7 +141,6 @@ private void tickerUpdate() mainTickerUpdate = updateCurrencyConversion() .flatMap(this::updateTickersFromOracle) .flatMap(this::fetchTickersSeparatelyIfRequired) - .flatMap(this::addArtisTicker) .map(this::checkTickers) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -493,20 +491,6 @@ public TokenTicker getEthTicker(long chainId) return ethTickers.get(chainId); } - private Single addArtisTicker(int tickerCount) - { - return convertPair("EUR", currentCurrencySymbolTxt) - .flatMap(this::getSigmaTicker) - .map(this::addArtisTickers) - .map(ticker -> (tickerCount + 2)); - } - - private TokenTicker addArtisTickers(TokenTicker tokenTicker) - { - ethTickers.put(ARTIS_SIGMA1_ID, tokenTicker); - return tokenTicker; - } - private TokenTicker decodeCoinGeckoTicker(JSONObject eth) { TokenTicker tTicker; @@ -646,17 +630,6 @@ public void addCustomTicker(long chainId, String address, TokenTicker ticker) } } - private Single getSigmaTicker(double rate) - { - return Single.fromCallable(() -> { - String percentageChange = "0.00"; - double conversion = (1.0 / 13.7603) * rate; //13.7603 ATS = 1 EUR - String price_usd = String.valueOf(conversion); - String image = "https://artis.eco/i/favicon.png"; - return new TokenTicker(price_usd, percentageChange, currentCurrencySymbolTxt, image, System.currentTimeMillis()); - }); - } - private void onTickersError(Throwable throwable) { mainTickerUpdate = null; diff --git a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java index f6d54bd92b..5910f8b275 100644 --- a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java +++ b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java @@ -2,7 +2,6 @@ import static com.alphawallet.app.repository.EthereumNetworkBase.COVALENT; import static com.alphawallet.app.repository.TokensRealmSource.databaseKey; -import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_TAU1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_TESTNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_MAIN_ID; @@ -46,6 +45,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -55,6 +55,7 @@ import io.reactivex.Single; import io.reactivex.schedulers.Schedulers; +import io.realm.Case; import io.realm.Realm; import io.realm.RealmResults; import io.realm.Sort; @@ -67,11 +68,15 @@ public class TransactionsNetworkClient implements TransactionsNetworkClientType private static final String TAG = "TXNETCLIENT"; private final int PAGESIZE = 800; private final int SYNC_PAGECOUNT = 2; //how many pages to read when we first sync the account - means we store the first 1600 transactions only - public static final int TRANSFER_RESULT_MAX = 250; //check 200 records when we first get a new account + private final int TRANSFER_RESULT_MAX = 500; //Note: if user wants to view transactions older than this, we fetch from etherscan on demand. //Generally this would only happen when watching extremely active accounts for curiosity private final String BLOCK_ENTRY = "-erc20blockCheck-"; - private final int AUX_DATABASE_ID = 30; //increment this to do a one off refresh the AUX database, in case of changed design etc + private final int AUX_DATABASE_ID = 25; //increment this to do a one off refresh the AUX database, in case of changed design etc + + private final int TRANSACTION_FETCH_LIMIT = 20; //Limit on the number of transactions fetched when we receive transfer updates + //Note that if the tx isn't fetched here, it is fetched automatically if the user scrolls down their activity list + //This speeds up the first time account sync - potentially there may be hundreds of new transactions here private final String DB_RESET = BLOCK_ENTRY + AUX_DATABASE_ID; private final String ETHERSCAN_API_KEY; private final String BSC_EXPLORER_API_KEY; @@ -413,6 +418,8 @@ else if (networkInfo.chainId == OKX_ID) * This is the function called when a user scrolls to the bottom of a transaction list. * First try to provide more transactions from the stored database. If there aren't any more then populate another page (800) from etherscan * + * TODO: We should also check transfers over the same block range + * * @param svs * @param network * @param lastTxTime @@ -481,21 +488,48 @@ public Single readTransfers(String walletAddress, NetworkInfo networkIn private EtherscanEvent[] fetchEvents(Realm instance, String walletAddress, NetworkInfo networkInfo, TransferFetchType tfType) throws JSONException { EtherscanEvent[] events; - //get last tokencheck - long lastBlockChecked = getTokenBlockRead(instance, networkInfo.chainId, tfType); + List eventList = new ArrayList<>(); + //get oldest record + long lastBlockFound = getTokenBlockRead(instance, networkInfo.chainId, tfType); if (networkInfo.chainId == OKX_ID) { - events = OkLinkService.get(httpClient).getEtherscanEvents(walletAddress, lastBlockChecked, tfType); + events = OkLinkService.get(httpClient).getEtherscanEvents(walletAddress, lastBlockFound, tfType); + eventList = new ArrayList<>(Arrays.asList(events)); } else { - //fetch transfers from end point - String fetchTransactions = readNextTxBatch(walletAddress, networkInfo, lastBlockChecked, tfType.getValue()); - events = getEtherscanEvents(fetchTransactions); + long upperBlock = 99999999999L; + long lowerBlock = (lastBlockFound == 0) ? 1 : lastBlockFound; + + while (true) + { + String fetchTransactions = readNextTxBatch(walletAddress, networkInfo, upperBlock, lowerBlock, tfType.getValue()); + events = getEtherscanEvents(fetchTransactions); + + if (events.length == 0) + { + break; + } + + upperBlock = Long.parseLong(events[events.length - 1].blockNumber) - 1; + eventList.addAll(Arrays.asList(events)); + if (events.length == TRANSFER_RESULT_MAX && eventList.size() > TRANSFER_RESULT_MAX) + { + //If still above the last read, blank all following reads to avoid 'sync-holes'. The new events read above will be added on the return + //TODO: See above - need to sync the lowest block here to the lowest block in the transaction reads + // This is so we can add a 'view all transactions' button which takes the user to the relevant Etherscan/Blockscout page. + blankTransferData(instance, networkInfo.chainId); + } + + if (eventList.size() > TRANSFER_RESULT_MAX || events.length < TRANSFER_RESULT_MAX) + { + break; + } + } } - return events; + return eventList.toArray(new EtherscanEvent[0]); } private int processEtherscanEvents(Realm instance, String walletAddress, NetworkInfo networkInfo, @@ -637,18 +671,17 @@ private void writeAssets (Map> eventMap, Token to } } - private String readNextTxBatch(String walletAddress, NetworkInfo networkInfo, long currentBlock, String queryType) + private String readNextTxBatch(String walletAddress, NetworkInfo networkInfo, long upperBlock, long lowerBlock, String queryType) { if (TextUtils.isEmpty(networkInfo.etherscanAPI) || networkInfo.etherscanAPI.contains(COVALENT)) return JSON_EMPTY_RESULT; //Covalent transfers are handled elsewhere String result = JSON_EMPTY_RESULT; - if (currentBlock == 0) currentBlock = 1; + if (lowerBlock == 0) lowerBlock = 1; String fullUrl = networkInfo.etherscanAPI + "module=account&action=" + queryType + - "&startblock=" + currentBlock + "&endblock=9999999999" + + "&startblock=" + lowerBlock + "&endblock=" + upperBlock + "&address=" + walletAddress + "&page=1&offset=" + TRANSFER_RESULT_MAX + - "&sort=asc" + getNetworkAPIToken(networkInfo); - + "&sort=desc" + getNetworkAPIToken(networkInfo); if (networkInfo.isCustom && !Utils.isValidUrl(networkInfo.etherscanAPI)) { @@ -675,7 +708,7 @@ private String readNextTxBatch(String walletAddress, NetworkInfo networkInfo, lo } catch (Exception e) { - if (networkInfo.chainId != ARTIS_TAU1_ID && BuildConfig.DEBUG) Timber.e(e); + Timber.e(e); } return result; @@ -1004,7 +1037,10 @@ private long writeEvents (Realm instance, EtherscanEvent[] events, String wall //For now; just use first token ev.patchFirstTokenID(); - String valueList = VALUES.replace(TO_TOKEN, ev.to).replace(FROM_TOKEN, ev.from).replace(AMOUNT_TOKEN, scanAsNFT ? ev.tokenID : ev.value); + //Sometimes the value for TokenID in Etherscan is in the value field. + String tokenValue = (scanAsNFT && ev.tokenID != null) ? ev.tokenID : (ev.value != null) ? ev.value : "0"; + + String valueList = VALUES.replace(TO_TOKEN, ev.to).replace(FROM_TOKEN, ev.from).replace(AMOUNT_TOKEN, tokenValue); if (!TextUtils.isEmpty(ev.tokenValue)) { valueList = valueList + "count,uint256," + ev.tokenValue; @@ -1023,7 +1059,7 @@ private long writeEvents (Realm instance, EtherscanEvent[] events, String wall } instance.executeTransaction(r -> { - storeTransferData(r, transferEventMap); + storeTransferData(r, networkInfo.chainId, transferEventMap); storeTransactions(r, txWriteMap, networkInfo.etherscanAPI.contains(COVALENT) ? null : txFetches); //store the transaction data and initiate tx fetch if not already known }); @@ -1074,12 +1110,12 @@ public TransferEvent(String valueList, String activityName, String contractAddre } } - private void storeTransferData(Realm instance, Map> transferEventMap) + private void storeTransferData(Realm instance, long chainId, Map> transferEventMap) { for (Map.Entry> entry : transferEventMap.entrySet()) { RealmTransfer realmPeek = instance.where(RealmTransfer.class) - .equalTo("hash", entry.getKey()) + .equalTo("hash", RealmTransfer.databaseKey(chainId, entry.getKey())) .findFirst(); if (realmPeek != null) continue; @@ -1088,7 +1124,7 @@ private void storeTransferData(Realm instance, Map> for (TransferEvent thisEvent : entry.getValue()) { RealmTransfer realmTransfer = instance.createObject(RealmTransfer.class); - realmTransfer.setHash(entry.getKey()); + realmTransfer.setHashKey(chainId, entry.getKey()); realmTransfer.setTokenAddress(thisEvent.contractAddress); realmTransfer.setEventName(thisEvent.activityName); realmTransfer.setTransferDetail(thisEvent.valueList); @@ -1096,6 +1132,17 @@ private void storeTransferData(Realm instance, Map> } } + private void blankTransferData(Realm instance, long chainId) + { + instance.executeTransaction(r -> { + RealmResults realmTx = r.where(RealmTransfer.class) + .like("hash", "*-" + chainId, Case.INSENSITIVE) + .findAll(); + + realmTx.deleteAllFromRealm(); + }); + } + /** * Write the transaction to Realm * @@ -1136,9 +1183,14 @@ else if (realmTx.getContractAddress() == null || !realmTx.getContractAddress().e */ private void fetchRequiredTransactions(long chainId, HashSet txFetches, String walletAddress) { + int txLimitCount = 0; for (String txHash : txFetches) { TransactionsService.addTransactionHashFetch(txHash, chainId, walletAddress); + if (txLimitCount++ > TRANSACTION_FETCH_LIMIT) + { + break; + } } } diff --git a/app/src/main/java/com/alphawallet/app/service/TransactionsService.java b/app/src/main/java/com/alphawallet/app/service/TransactionsService.java index 798ce80e26..6c2768eab3 100644 --- a/app/src/main/java/com/alphawallet/app/service/TransactionsService.java +++ b/app/src/main/java/com/alphawallet/app/service/TransactionsService.java @@ -135,7 +135,7 @@ private void readTransferCycle() { if (tokenTransferCheckCycle != null && !tokenTransferCheckCycle.isDisposed()) tokenTransferCheckCycle.dispose(); - tokenTransferCheckCycle = Observable.interval(firstCycle ? START_CHECK_DELAY / 3 : (START_CHECK_DELAY * 15) + 1, + tokenTransferCheckCycle = Observable.interval(firstCycle ? START_CHECK_DELAY : (START_CHECK_DELAY * 15) + 1, firstCycle ? CHECK_CYCLE / 3 : CHECK_CYCLE, TimeUnit.SECONDS) .doOnNext(l -> checkTransfers()).subscribe(); } @@ -181,8 +181,12 @@ private void checkTransfers() } long chainId = filters.get(currentChainIndex); - readTokenMoves(chainId); //check NFTs for same chain on next iteration or advance to next chain - currentChainIndex = getNextChainIndex(currentChainIndex, chainId, filters); + boolean initiateRead = readTokenMoves(chainId); //check NFTs for same chain on next iteration or advance to next chain + + if (initiateRead) + { + currentChainIndex = getNextChainIndex(currentChainIndex, chainId, filters); + } } private int getNextChainIndex(int currentIndex, long chainId, List filters) @@ -228,11 +232,20 @@ private void setNextTransferCheck(long chainId, boolean isNft) } } - private void readTokenMoves(long chainId) + private boolean readTokenMoves(long chainId) { //check if this route has combined NFT final NetworkInfo info = ethereumNetworkRepository.getNetworkByChain(chainId); - if (info == null || info.getTransferQueriesUsed().length == 0) return; + if (info == null || info.getTransferQueriesUsed().length == 0) + { + return true; + } + + if (eventFetch != null && !eventFetch.isDisposed()) + { + return false; + } + TransferFetchType tfType = apiFetchProgress.get(chainId, TransferFetchType.ERC_20); if (tfType.ordinal() > 0) { @@ -244,6 +257,8 @@ private void readTokenMoves(long chainId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(count -> handleMoveCheck(info.chainId, tfType.ordinal() > 0), this::gotReadErr); + + return true; } private void gotReadErr(Throwable e) @@ -627,7 +642,7 @@ private void checkPendingTransactions() } } - public Single fetchTransaction(String currentAddress, String hash, long chainId) + public Single fetchTransaction(String currentAddress, long chainId, String hash) { return doTransactionFetch(hash, chainId) .map(fetchedTx -> { diff --git a/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java b/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java index 2c11c8253a..546f932508 100644 --- a/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java @@ -159,7 +159,7 @@ private List getTokenTransfersForHash(Realm realm, Transactio //summon realm items //get matching entries for this transaction RealmResults transfers = realm.where(RealmTransfer.class) - .equalTo("hash", tm.hash) + .equalTo("hash", RealmTransfer.databaseKey(tm.chainId, tm.hash)) .findAll(); if (transfers != null && transfers.size() > 0) diff --git a/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java b/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java index eb5bff8c08..312747c662 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java @@ -157,11 +157,7 @@ public void onResume() { progressBar.setVisibility(View.VISIBLE); viewModel.prepare(); - if (asset == null || !asset.isAttestation()) - { - viewModel.getAsset(token, tokenId); - progressBar.setVisibility(View.VISIBLE); - } + getIntentData(); tokenImage.onResume(); } else @@ -249,10 +245,10 @@ private void getIntentData() } else { - Wallet wallet = getIntent().getParcelableExtra(C.Key.WALLET); - viewModel.loadWallet(wallet.address); - token = resolveAssetToken(); - setup(); + Wallet wallet = getIntent().getParcelableExtra(C.Key.WALLET); + viewModel.loadWallet(wallet.address); + token = resolveAssetToken(); + setup(); } } @@ -284,6 +280,7 @@ private void onActiveWalletFetched(Wallet activeWallet) { showWarnDialog(walletAddress); } + asset = token.getAssetForToken(tokenId); setup(); } } @@ -293,10 +290,7 @@ private void showWarnDialog(String walletAddress) AWalletAlertDialog alertDialog = new AWalletAlertDialog(this); alertDialog.setIcon(WARNING); alertDialog.setMessage(getApplicationContext().getString(R.string.warn_asset_not_belongs_to_active_wallet, Utils.formatAddress(walletAddress))); - alertDialog.setButton(R.string.yes_continue, v -> - { - alertDialog.dismiss(); - }); + alertDialog.setButton(R.string.yes_continue, v -> alertDialog.dismiss()); alertDialog.setSecondaryButton(R.string.dialog_cancel_back, view -> { alertDialog.dismiss(); finish(); @@ -381,7 +375,7 @@ private void setupFunctionBar(Wallet wallet) if (BuildConfig.DEBUG || wallet.type != WalletType.WATCH) { FunctionButtonBar functionBar = findViewById(R.id.layoutButtons); - if (asset.isAttestation()) + if (asset != null && asset.isAttestation()) { functionBar.setupAttestationFunctions(this, viewModel.getAssetDefinitionService(), token, null); } diff --git a/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java b/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java index 9724d0e8fb..6213af0b4e 100644 --- a/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java @@ -391,7 +391,7 @@ private void displayTransferTokens(List nftAssets, Transaction transac if (transaction.transactionInput == null || transaction.transactionInput.type == TransactionType.CONTRACT_CALL) { - eventAction.setText(transferData.getTitle(transaction)); + eventAction.setText(transferData.getTitle()); } } } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/TokenTransferData.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/TokenTransferData.java index 569e366b45..09ca01ba2a 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/entity/TokenTransferData.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/TokenTransferData.java @@ -37,7 +37,7 @@ public TokenTransferData(String hash, long chainId, String tokenAddress, String this.transferDetail = transferDetail; } - public int getTitle(Transaction tx) + public int getTitle() { //catch standard Token events switch (eventName) diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/holder/TransferHolder.java b/app/src/main/java/com/alphawallet/app/ui/widget/holder/TransferHolder.java index f858ce8c95..de835e9c05 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/holder/TransferHolder.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/holder/TransferHolder.java @@ -9,6 +9,7 @@ import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; +import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; @@ -34,28 +35,33 @@ import java.math.BigInteger; import java.util.Map; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + /** * Created by JB on 17/12/2020. */ public class TransferHolder extends BinderViewHolder implements View.OnClickListener { public static final int VIEW_TYPE = 2017; - private final TokenIcon tokenIcon; private final TextView date; private final TextView type; private final TextView address; private final TextView value; - + private final ProgressBar txLoad; private final AssetDefinitionService assetDefinition; private Token token; private TokenTransferData transferData; - private final FetchTransactionsInteract fetchTransactionsInteract; private final TokensService tokensService; private String hashKey; private boolean fromTokenView; + @Nullable + private Disposable disposable; + public TransferHolder(ViewGroup parent, TokensService service, FetchTransactionsInteract interact, AssetDefinitionService svs) { @@ -65,12 +71,12 @@ public TransferHolder(ViewGroup parent, TokensService service, FetchTransactions address = findViewById(R.id.address); type = findViewById(R.id.type); value = findViewById(R.id.value); + txLoad = findViewById(R.id.loading_transaction); tokensService = service; itemView.setOnClickListener(this); assetDefinition = svs; fetchTransactionsInteract = interact; - } @Override @@ -79,19 +85,45 @@ public void bind(@Nullable TokenTransferData data, @NonNull Bundle addition) fromTokenView = false; transferData = data; String walletAddress = addition.getString(DEFAULT_ADDRESS_ADDITIONAL); + + token = tokensService.getToken(data.chainId, data.tokenAddress); + if (token == null) + { + token = tokensService.getToken(data.chainId, walletAddress); + } + //pull event details from DB Transaction tx = fetchTransactionsInteract.fetchCached(walletAddress, data.hash); - token = tokensService.getToken(data.chainId, data.tokenAddress); - if (tx == null) { return; } + if (disposable != null && !disposable.isDisposed()) + { + disposable.dispose(); + } + + tokenIcon.bindData(token, assetDefinition); - if (token == null) + //We haven't yet fetched the underlying transaction. Fetch and display + if (tx == null) { - token = tokensService.getToken(data.chainId, walletAddress); + txLoad.setVisibility(View.VISIBLE); + //load the transaction and restart the bind. + disposable = fetchTransactionsInteract.fetchFromNode(walletAddress, data.chainId, data.hash) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(fetchedTransaction -> bindView(data, fetchedTransaction), + err -> bindView(data, null)); //Can still build limited view with no fetched tx - better than a blank view + } + else + { + bindView(data, tx); } + } + + private void bindView(TokenTransferData data, Transaction tx) + { + txLoad.setVisibility(View.GONE); String sym = token != null ? token.getShortSymbol() : getContext().getString(R.string.eth); - tokenIcon.bindData(token, assetDefinition); String itemView = null; if (data.getTimeStamp() % 1000 != 0) @@ -121,7 +153,7 @@ public void bind(@Nullable TokenTransferData data, @NonNull Bundle addition) value.setText(getString(R.string.valueSymbol, transactionValue, sym)); } - CharSequence typeValue = Utils.createFormattedValue(getContext(), getTitle(data, tx), token); + CharSequence typeValue = Utils.createFormattedValue(getContext(), getTitle(data), token); type.setText(typeValue); address.setText(data.getDetail(getContext(), tx, token, itemView)); @@ -148,7 +180,11 @@ private String getEventAmount(TokenTransferData eventData, Transaction tx) return ""; } - tx.getDestination(token); //build decoded input + if (tx != null) + { + tx.getDestination(token); //build decoded input + } + Map resultMap = eventData.getEventResultMap(); String value = ""; switch (eventData.eventName) @@ -171,7 +207,7 @@ private String getEventAmount(TokenTransferData eventData, Transaction tx) } break; default: - if (token != null) + if (token != null && tx != null) { value = token.isEthereum() ? token.getTransactionValue(tx, TRANSACTION_BALANCE_PRECISION) : tx.getOperationResult(token, TRANSACTION_BALANCE_PRECISION); } @@ -181,10 +217,10 @@ private String getEventAmount(TokenTransferData eventData, Transaction tx) return value; } - private String getTitle(TokenTransferData eventData, Transaction tx) + private String getTitle(TokenTransferData eventData) { //TODO: pick up item-view - int titleResource = eventData.getTitle(tx); + int titleResource = eventData.getTitle(); if (titleResource == 0) { return eventData.eventName; diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/Erc1155AssetListViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/Erc1155AssetListViewModel.java index ef22d53606..8aa0217b94 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/Erc1155AssetListViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/Erc1155AssetListViewModel.java @@ -46,6 +46,7 @@ public Intent showAssetDetailsIntent(Context context, Wallet wallet, Token token intent.putExtra(C.Key.WALLET, wallet); intent.putExtra(C.EXTRA_CHAIN_ID, token.tokenInfo.chainId); intent.putExtra(C.EXTRA_ADDRESS, token.getAddress()); + intent.putExtra(C.EXTRA_NFTASSET, token.getAssetForToken(tokenId)); intent.putExtra(C.EXTRA_TOKEN_ID, tokenId.toString()); intent.putExtra(C.EXTRA_STATE, ERC1155Token.getNFTTokenId(tokenId).toString()); return intent; diff --git a/app/src/main/java/com/alphawallet/app/widget/ActivityHistoryList.java b/app/src/main/java/com/alphawallet/app/widget/ActivityHistoryList.java index 75d88c4547..eb9729c1bb 100644 --- a/app/src/main/java/com/alphawallet/app/widget/ActivityHistoryList.java +++ b/app/src/main/java/com/alphawallet/app/widget/ActivityHistoryList.java @@ -131,7 +131,7 @@ private List getRelevantTransfersForHash(TransactionMeta tm, //summon realm items //get matching entries for this transaction RealmResults transfers = realm.where(RealmTransfer.class) - .equalTo("hash", tm.hash) + .equalTo("hash", RealmTransfer.databaseKey(tm.chainId, tm.hash)) .findAll(); if (transfers != null && transfers.size() > 0) diff --git a/app/src/main/res/layout/item_transaction.xml b/app/src/main/res/layout/item_transaction.xml index 157e529609..c9718acba0 100644 --- a/app/src/main/res/layout/item_transaction.xml +++ b/app/src/main/res/layout/item_transaction.xml @@ -21,6 +21,15 @@ android:layout_gravity="center" android:orientation="horizontal"> + + - \ No newline at end of file + diff --git a/app/src/test/java/com/alphawallet/app/QRSelectionTest.java b/app/src/test/java/com/alphawallet/app/QRSelectionTest.java index b855e836e2..67042c9e3d 100644 --- a/app/src/test/java/com/alphawallet/app/QRSelectionTest.java +++ b/app/src/test/java/com/alphawallet/app/QRSelectionTest.java @@ -175,6 +175,12 @@ public Single sendTransaction(Wallet from, RawTransaction rtx, Signature { return null; } + + @Override + public Single fetchTransactionFromNode(String walletAddress, long chainId, String hash) + { + return null; + } }; signatureGenerateInteract = new SignatureGenerateInteract(null) diff --git a/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java b/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java index 45ed4c8a5a..97795c8880 100644 --- a/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java +++ b/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java @@ -10,8 +10,6 @@ public class EthRPCNodes private static final String CLASSIC_RPC_URL = "https://www.ethercluster.com/etc"; private static final String XDAI_RPC_URL = EthereumNetworkBase.XDAI_RPC_URL; private static final String GOERLI_RPC_URL = "https://goerli.infura.io/v3/" + getInfuraKey(); - private static final String ARTIS_SIGMA1_RPC_URL = "https://rpc.sigma1.artis.network"; - private static final String ARTIS_TAU1_RPC_URL = "https://rpc.tau1.artis.network"; public static String getNodeURLByNetworkId(long networkId) { @@ -24,10 +22,6 @@ public static String getNodeURLByNetworkId(long networkId) { return XDAI_RPC_URL; case (int)EthereumNetworkBase.GOERLI_ID: return GOERLI_RPC_URL; - case (int)EthereumNetworkBase.ARTIS_SIGMA1_ID: - return ARTIS_SIGMA1_RPC_URL; - case (int)EthereumNetworkBase.ARTIS_TAU1_ID: - return ARTIS_TAU1_RPC_URL; default: return MAINNET_RPC_URL; } diff --git a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java index 4fe9f5432b..76311ec65d 100644 --- a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java +++ b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java @@ -13,8 +13,6 @@ public abstract class EthereumNetworkBase public static final long CLASSIC_ID = 61; public static final long GNOSIS_ID = 100; public static final long GOERLI_ID = 5; - public static final long ARTIS_SIGMA1_ID = 246529; - public static final long ARTIS_TAU1_ID = 246785; public static final long BINANCE_TEST_ID = 97; public static final long BINANCE_MAIN_ID = 56; public static final long HECO_ID = 128; @@ -49,8 +47,6 @@ public abstract class EthereumNetworkBase public static final String CLASSIC_RPC_URL = "https://www.ethercluster.com/etc"; public static final String XDAI_RPC_URL = "https://rpc.gnosischain.com"; public static final String GOERLI_RPC_URL = "https://goerli.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; - public static final String ARTIS_SIGMA1_RPC_URL = "https://rpc.sigma1.artis.network"; - public static final String ARTIS_TAU1_RPC_URL = "https://rpc.tau1.artis.network"; public static final String BINANCE_TEST_RPC_URL = "https://data-seed-prebsc-1-s3.binance.org:8545"; public static final String BINANCE_MAIN_RPC_URL = "https://bsc-dataseed.binance.org"; public static final String HECO_RPC_URL = "https://http-mainnet.hecochain.com"; @@ -89,12 +85,8 @@ public abstract class EthereumNetworkBase CLASSIC_ID, false)); put(GNOSIS_ID, new NetworkInfo("Gnosis", "xDAi", XDAI_RPC_URL, "https://blockscout.com/xdai/mainnet/tx/", GNOSIS_ID, false)); - put(ARTIS_SIGMA1_ID, new NetworkInfo("ARTIS sigma1", "ATS", ARTIS_SIGMA1_RPC_URL, "https://explorer.sigma1.artis.network/tx/", - ARTIS_SIGMA1_ID, false)); put(GOERLI_ID, new NetworkInfo("Görli (Test)", "GÖETH", GOERLI_RPC_URL, "https://goerli.etherscan.io/tx/", GOERLI_ID, false)); - put(ARTIS_TAU1_ID, new NetworkInfo("ARTIS tau1 (Test)", "ATS", ARTIS_TAU1_RPC_URL, "https://explorer.tau1.artis.network/tx/", - ARTIS_TAU1_ID, false)); put(BINANCE_TEST_ID, new NetworkInfo("BSC TestNet (Test)", "T-BSC", BINANCE_TEST_RPC_URL, "https://explorer.binance.org/smart-testnet/tx/", BINANCE_TEST_ID, false)); put(BINANCE_MAIN_ID, new NetworkInfo("Binance (BSC)", "BSC", BINANCE_MAIN_RPC_URL, "https://explorer.binance.org/smart/tx/", diff --git a/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java b/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java index 56cee92285..d5a2008b0d 100644 --- a/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java +++ b/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java @@ -3,8 +3,6 @@ import com.alphawallet.ethereum.EthereumNetworkBase; import com.alphawallet.ethereum.NetworkInfo; -import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_SIGMA1_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_TAU1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.CLASSIC_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.GOERLI_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; @@ -61,10 +59,6 @@ public static String getMagicLinkDomainFromNetworkId(long networkId) { return xDaiMagicLinkDomain; case (int)GOERLI_ID: return goerliMagicLinkDomain; - case (int)ARTIS_SIGMA1_ID: - return artisSigma1MagicLinkDomain; - case (int)ARTIS_TAU1_ID: - return artisTau1MagicLinkDomain; } } @@ -83,10 +77,6 @@ public static long getNetworkIdFromDomain(String domain) { return GNOSIS_ID; case goerliMagicLinkDomain: return GOERLI_ID; - case artisSigma1MagicLinkDomain: - return ARTIS_SIGMA1_ID; - case artisTau1MagicLinkDomain: - return ARTIS_TAU1_ID; } } @@ -102,10 +92,6 @@ public static String getEtherscanURLbyNetwork(long networkId) { return xDaiEtherscan; case (int)GOERLI_ID: return goerliEtherscan; - case (int)ARTIS_SIGMA1_ID: - return artisSigma1Etherscan; - case (int)ARTIS_TAU1_ID: - return artisTau1Etherscan; } }