diff --git a/app/build.gradle b/app/build.gradle
index e8793f7983..a29348ce77 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -255,8 +255,7 @@ dependencies {
     // WARNING! WARNING!  WARNING!  WARNING!  WARNING!  WARNING!  WARNING!  WARNING!
 
     // Ethereum client
-    //implementation "org.web3j:core:4.8.8-android"
-    implementation fileTree(include: ['*.jar'], dir: 'libs')
+    implementation "org.web3j:core:4.8.8-android"
     implementation 'com.fasterxml.jackson.core:jackson-core:2.13.3'
     implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3'
     implementation 'org.slf4j:slf4j-api:2.0.0-alpha7'
diff --git a/app/libs/abi-4.8.8-android.jar b/app/libs/abi-4.8.8-android.jar
deleted file mode 100644
index 889de4d8d6..0000000000
Binary files a/app/libs/abi-4.8.8-android.jar and /dev/null differ
diff --git a/app/libs/core-4.8.8-android.jar b/app/libs/core-4.8.8-android.jar
deleted file mode 100644
index 4d7cf4511e..0000000000
Binary files a/app/libs/core-4.8.8-android.jar and /dev/null differ
diff --git a/app/libs/crypto-4.8.8-android.jar b/app/libs/crypto-4.8.8-android.jar
deleted file mode 100644
index b14d4eec73..0000000000
Binary files a/app/libs/crypto-4.8.8-android.jar and /dev/null differ
diff --git a/app/libs/rlp-4.8.8-android.jar b/app/libs/rlp-4.8.8-android.jar
deleted file mode 100644
index 5d4a4ead9a..0000000000
Binary files a/app/libs/rlp-4.8.8-android.jar and /dev/null differ
diff --git a/app/libs/utils-4.8.8-android.jar b/app/libs/utils-4.8.8-android.jar
deleted file mode 100644
index a4500aa0d8..0000000000
Binary files a/app/libs/utils-4.8.8-android.jar and /dev/null differ
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 a7ea9d5f44..786ed56389 100644
--- a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java
+++ b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java
@@ -14,7 +14,6 @@
 import android.content.Context;
 import android.view.KeyEvent;
 import android.view.View;
-
 import android.view.inputmethod.InputMethodManager;
 
 import androidx.test.espresso.PerformException;
@@ -25,16 +24,13 @@
 import androidx.test.espresso.util.HumanReadables;
 import androidx.test.espresso.util.TreeIterables;
 
-import org.hamcrest.Matcher;
-import org.hamcrest.Matchers;
-
-import java.util.concurrent.TimeoutException;
 import com.alphawallet.app.R;
 
 import org.hamcrest.Matcher;
 import org.hamcrest.Matchers;
 
 import java.util.concurrent.TimeoutException;
+import java.util.stream.Stream;
 
 public class Helper
 {
@@ -80,12 +76,10 @@ public void perform(final UiController uiController, final View view)
 
                 do
                 {
-                    for (View child : TreeIterables.breadthFirstViewTraversal(view.getRootView()))
+                    Iterable<View> views = TreeIterables.breadthFirstViewTraversal(view.getRootView());
+                    if (Stream.of(views).anyMatch(matcher::matches))
                     {
-                        if (matcher.matches(child))
-                        {
-                            return;
-                        }
+                        return;
                     }
 
                     uiController.loopMainThreadForAtLeast(50);
diff --git a/app/src/main/java/com/alphawallet/app/entity/ContractLocator.java b/app/src/main/java/com/alphawallet/app/entity/ContractLocator.java
index d7c67fcc6c..2c39378552 100644
--- a/app/src/main/java/com/alphawallet/app/entity/ContractLocator.java
+++ b/app/src/main/java/com/alphawallet/app/entity/ContractLocator.java
@@ -1,5 +1,7 @@
 package com.alphawallet.app.entity;
 
+import static java.util.stream.Collectors.toList;
+
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -9,6 +11,7 @@
 import com.alphawallet.token.entity.ContractInfo;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -44,7 +47,7 @@ protected ContractLocator(Parcel in)
 
     public boolean equals(Token token)
     {
-        return (token != null && address != null && chainId == token.tokenInfo.chainId && address.equalsIgnoreCase(token.getAddress()) );
+        return (token != null && address != null && chainId == token.tokenInfo.chainId && address.equalsIgnoreCase(token.getAddress()));
     }
 
     public boolean equals(TokenCardMeta token)
@@ -52,13 +55,12 @@ public boolean equals(TokenCardMeta token)
         return TokensRealmSource.databaseKey(chainId, address).equalsIgnoreCase(token.tokenId);
     }
 
-    /* replace this with a one-liner use of stream when we up our minSdkVersion to 24 */
-    public static ContractLocator[] fromAddresses(String[] addresses, long chainID) {
-        ContractLocator[] retval = new ContractLocator[addresses.length];
-        for (int i=0; i<addresses.length; i++) {
-            retval[i] = new ContractLocator(addresses[i], chainID);
-        }
-        return retval;
+    public static ContractLocator[] fromAddresses(String[] addresses, long chainID)
+    {
+        return Arrays.stream(addresses)
+                .map(address -> new ContractLocator(address, chainID))
+                .collect(toList())
+                .toArray(new ContractLocator[]{});
     }
 
     public static List<ContractLocator> fromContractInfo(ContractInfo cInfo)
@@ -76,14 +78,17 @@ public static List<ContractLocator> fromContractInfo(ContractInfo cInfo)
         return retVal;
     }
 
-    public static final Creator<ContractLocator> CREATOR = new Creator<ContractLocator>() {
+    public static final Creator<ContractLocator> CREATOR = new Creator<ContractLocator>()
+    {
         @Override
-        public ContractLocator createFromParcel(Parcel in) {
+        public ContractLocator createFromParcel(Parcel in)
+        {
             return new ContractLocator(in);
         }
 
         @Override
-        public ContractLocator[] newArray(int size) {
+        public ContractLocator[] newArray(int size)
+        {
             return new ContractLocator[size];
         }
     };
diff --git a/app/src/main/java/com/alphawallet/app/entity/TransactionDecoder.java b/app/src/main/java/com/alphawallet/app/entity/TransactionDecoder.java
index 2a22edb640..c74ab5040a 100644
--- a/app/src/main/java/com/alphawallet/app/entity/TransactionDecoder.java
+++ b/app/src/main/java/com/alphawallet/app/entity/TransactionDecoder.java
@@ -19,7 +19,7 @@
 
 /**
  * Created by James on 2/02/2018.
- *
+ * <p>
  * TransactionDecoder currently only decode a transaction input in the
  * string format, which is strictly a string starting with "0x" and
  * with an even number of hex digits followed. (Probably should be
@@ -468,17 +468,13 @@ public Sign.SignatureData getSignatureData(TransactionInput data)
 
     public int[] getIndices(TransactionInput data)
     {
-        int[] indices = null;
-        if (data != null && data.arrayValues != null)
+        if (data == null || data.arrayValues == null)
         {
-            indices = new int[data.arrayValues.size()];
-            for (int i = 0; i < data.arrayValues.size(); i++)
-            {
-                indices[i] = data.arrayValues.get(i).intValue();
-            }
+            return null;
         }
-
-        return indices;
+        return data.arrayValues.stream()
+                .mapToInt(BigInteger::intValue)
+                .toArray();
     }
 
     public static String buildMethodId(String methodSignature)
diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/Ticket.java b/app/src/main/java/com/alphawallet/app/entity/tokens/Ticket.java
index 44e5b85115..a3c308107f 100644
--- a/app/src/main/java/com/alphawallet/app/entity/tokens/Ticket.java
+++ b/app/src/main/java/com/alphawallet/app/entity/tokens/Ticket.java
@@ -58,17 +58,20 @@ public Ticket(Token oldTicket, List<BigInteger> balances)
     }
 
     @Override
-    public String getStringBalanceForUI(int scale) {
+    public String getStringBalanceForUI(int scale)
+    {
         return String.valueOf(getTokenCount());
     }
 
     @Override
-    public boolean hasPositiveBalance() {
+    public boolean hasPositiveBalance()
+    {
         return (getTokenCount() > 0);
     }
 
     @Override
-    public String getFullBalance() {
+    public String getFullBalance()
+    {
         if (balanceArray == null) return "no tokens";
         else return Utils.bigIntListToString(balanceArray, true);
     }
@@ -88,7 +91,10 @@ public List<BigInteger> pruneIDList(String idListStr, int quantity)
         //       .map(s -> Numeric.toBigInt(s)).toList().blockingGet();
         if (quantity >= idList.size()) return idList;
         List<BigInteger> pruneList = new ArrayList<>();
-        for (int i = 0; i < quantity; i++) pruneList.add(idList.get(i));
+        for (int i = 0; i < quantity; i++)
+        {
+            pruneList.add(idList.get(i));
+        }
 
         return pruneList;
     }
@@ -96,15 +102,14 @@ public List<BigInteger> pruneIDList(String idListStr, int quantity)
     @Override
     public int getTokenCount()
     {
-        int count = 0;
-        if (balanceArray != null)
+        if (balanceArray == null)
         {
-            for (BigInteger id : balanceArray)
-            {
-                if (id.compareTo(BigInteger.ZERO) != 0) count++;
-            }
+            return 0;
         }
-        return count;
+
+        return (int) balanceArray.stream()
+                .filter(id -> id.compareTo(BigInteger.ZERO) != 0)
+                .count();
     }
 
     @Override
@@ -141,6 +146,7 @@ public int getContractType()
 
     /**
      * Convert a list of TicketID's into an Index list corresponding to those indices
+     *
      * @param ticketIds
      * @return
      */
@@ -181,6 +187,7 @@ public List<BigInteger> ticketIdListToIndexList(List<BigInteger> ticketIds)
 
     /**
      * Convert a String list of ticket IDs into a list of ticket indices
+     *
      * @param userList
      * @return
      */
@@ -194,7 +201,7 @@ public List<BigInteger> ticketIdStringToIndexList(String userList)
         for (String id : ids)
         {
             //remove whitespace
-            String     trim   = id.trim();
+            String trim = id.trim();
             BigInteger thisId = Numeric.toBigInt(trim);
             idList.add(thisId);
         }
@@ -230,7 +237,8 @@ private List<BigInteger> tokenIdsToTokenIndices(List<BigInteger> tokenIds)
                 }
             }
         }
-        catch (Exception e) {
+        catch (Exception e)
+        {
             indexList = null;
         }
 
@@ -285,7 +293,8 @@ protected org.web3j.abi.datatypes.DynamicArray getDynArray(List<BigInteger> indi
     }
 
     @Override
-    public boolean isToken() {
+    public boolean isToken()
+    {
         return false;
     }
 
@@ -296,7 +305,10 @@ public boolean hasArrayBalance()
     }
 
     @Override
-    public List<BigInteger> getArrayBalance() { return balanceArray; }
+    public List<BigInteger> getArrayBalance()
+    {
+        return balanceArray;
+    }
 
     @Override
     public List<BigInteger> getNonZeroArrayBalance()
@@ -316,10 +328,21 @@ public boolean getIsSent(Transaction transaction)
     }
 
     @Override
-    public boolean isERC875() { return true; }
-    public boolean isNonFungible() { return true; }
+    public boolean isERC875()
+    {
+        return true;
+    }
+
+    public boolean isNonFungible()
+    {
+        return true;
+    }
+
     @Override
-    public boolean hasGroupedTransfer() { return true; }
+    public boolean hasGroupedTransfer()
+    {
+        return true;
+    }
 
     @Override
     public boolean groupWithToken(TicketRange currentGroupingRange, TicketRangeElement newElement, long currentGroupTime)
@@ -333,6 +356,7 @@ public boolean groupWithToken(TicketRange currentGroupingRange, TicketRangeEleme
     /**
      * This function should return a String list of IDs suitable for submission to the token's transfer function
      * For ERC875 it is a list of indices, so convert this list of TokenIDs to indices
+     *
      * @param CSVstringIdList
      * @return
      */
@@ -346,6 +370,7 @@ public String getTransferListFormat(String CSVstringIdList)
     /**
      * This function takes a list of tokenIds, and returns a BigInteger list suitable for this token's transfer function
      * For ERC875 it is a list of indices, so convert this list of TokenIDs to indices
+     *
      * @param tokenIds
      * @return
      */
diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java
index 8273f0233a..a4636796eb 100644
--- a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java
+++ b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java
@@ -273,15 +273,7 @@ private String sanitiseString(String str)
         }
         else
         {
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
-            {
-                return Html.fromHtml(str, FROM_HTML_MODE_COMPACT).toString();
-            }
-            else
-            {
-                //noinspection deprecation
-                return Html.fromHtml(str).toString();
-            }
+            return Html.fromHtml(str, FROM_HTML_MODE_COMPACT).toString();
         }
     }
 
diff --git a/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java b/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java
index 3b95c76ec2..885c2cec6d 100644
--- a/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java
+++ b/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java
@@ -49,7 +49,8 @@ public class AlphaWalletService
 
     public AlphaWalletService(OkHttpClient httpClient,
                               TransactionRepositoryType transactionRepository,
-                              Gson gson) {
+                              Gson gson)
+    {
         this.httpClient = httpClient;
         this.transactionRepository = transactionRepository;
         this.gson = gson;
@@ -82,6 +83,7 @@ public Observable<Integer> handleFeemasterImport(String url, Wallet wallet, long
 
     /**
      * Use API to determine tokenscript validity
+     *
      * @param tokenScriptFile
      * @return
      */
@@ -165,9 +167,7 @@ private Single<int[]> generateTicketArray(String indices, Ticket ticket)
     {
         return Single.fromCallable(() -> {
             List<Integer> ticketIndices = Utils.stringIntsToIntegerList(indices);
-            int[] indicesArray = new int[ticketIndices.size()];
-            for (int i = 0; i < ticketIndices.size(); i++) indicesArray[i] = ticketIndices.get(i);
-            return indicesArray;
+            return ticketIndices.stream().mapToInt(Integer::intValue).toArray();
         });
     }
 
@@ -206,7 +206,8 @@ private Single<Integer> sendFeemasterTransaction(
             byte[] tradeSig,
             String contractAddress,
             List<BigInteger> tokenIds
-    ) {
+    )
+    {
         return Single.fromCallable(() -> {
             Integer result = 500; //fail by default
             try
@@ -317,7 +318,7 @@ public Single<Boolean> checkFeemasterService(String url, long chainId, String ad
 
                     okhttp3.Response response = httpClient.newCall(request).execute();
                     int resultCode = response.code();
-                    if ((resultCode/100) == 2) result = true;
+                    if ((resultCode / 100) == 2) result = true;
                     Timber.tag("RESP").d(response.body().string());
                 }
             }
diff --git a/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java b/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java
index 10fed50f97..bf307a1484 100644
--- a/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java
+++ b/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java
@@ -976,16 +976,7 @@ private void onError(Throwable throwable)
 
     private TokenDefinition parseFile(InputStream xmlInputStream) throws Exception
     {
-        Locale locale;
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
-        {
-            locale = context.getResources().getConfiguration().getLocales().get(0);
-        }
-        else
-        {
-            locale = context.getResources().getConfiguration().locale;
-        }
-
+        Locale locale = context.getResources().getConfiguration().getLocales().get(0);
         return new TokenDefinition(
                 xmlInputStream, locale, this);
     }
diff --git a/app/src/main/java/com/alphawallet/app/service/KeyService.java b/app/src/main/java/com/alphawallet/app/service/KeyService.java
index 085af98579..1bd479e395 100644
--- a/app/src/main/java/com/alphawallet/app/service/KeyService.java
+++ b/app/src/main/java/com/alphawallet/app/service/KeyService.java
@@ -90,7 +90,7 @@ public class KeyService implements AuthenticationCallback, PinAuthenticationCall
 {
     private static final String TAG = "HDWallet";
     private static final int AUTHENTICATION_DURATION_SECONDS = 30;
-    public  static final String FAILED_SIGNATURE = "00000000000000000000000000000000000000000000000000000000000000000";
+    public static final String FAILED_SIGNATURE = "00000000000000000000000000000000000000000000000000000000000000000";
     private static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM;
     private static final String PADDING = KeyProperties.ENCRYPTION_PADDING_NONE;
 
@@ -179,9 +179,9 @@ public void createNewHDKey(Activity callingActivity, CreateWalletCallbackInterfa
     /**
      * Create and encrypt/store an authentication-locked keystore password for importing a keystore.
      * Flow for importing a private key is almost identical
-     *
+     * <p>
      * Flow is as follows:
-     *
+     * <p>
      * 1. Obtain authentication event - pop up the unlock dialog.
      * 2. After authentication event, proceed to authenticatePass and switch through to createPassword()
      * 3. Create a new strong keystore password, store the password.
@@ -217,7 +217,7 @@ public void createPrivateKeyPassword(String address, Activity callingActivity, I
 
     /**
      * Encrypt and store mnemonic for HDWallet
-     *
+     * <p>
      * 1. Check valid seed phrase, generate HDWallet and store the mnemonic without authentication lock
      * 2. Obtain authentication event.
      * 3. After authentication pass through to authenticatePass and switch to importHDKey()
@@ -248,7 +248,7 @@ public void importHDKey(String seedPhrase, Activity callingActivity, ImportWalle
 
     /**
      * Fetch mnemonic from storage
-     *
+     * <p>
      * 1. call unpackMnemonic
      * 2. if authentication required, get authentication event and call unpackMnemonic
      * 3. return mnemonic to FetchMnemonic callback
@@ -322,12 +322,11 @@ public void setRequireAuthentication()
 
     /**
      * Upgrade key security
-     *
+     * <p>
      * 1. Get authentication, and then execute 'upgradeKey()' from authenticatePass
      * 2. Upgrade key reads the mnemonic/password, then calls storeEncryptedBytes with authentication.
      * 3. returns result and flow back to callee via signCallback.CreatedKey
      *
-     *
      * @param wallet
      * @param callingActivity
      * @return
@@ -348,10 +347,10 @@ public UpgradeKeyResult upgradeKeySecurity(Wallet wallet, Activity callingActivi
 
     /**
      * SignData
-     *
+     * <p>
      * Flow for this function is by necessity simpler - this function is called from code that doesn't have access to an Activity, so can't create
      * any signing dialog. The authentication event must be generated prior to entering the signing flow.
-     *
+     * <p>
      * If HDWallet - decrypt mnemonic, regenerate private key, generate digest, sign digest using Trezor libs.
      * If Keystore - fetch keystore JSON file, decrypt keystore password, regenerate Web3j Credentials and sign.
      *
@@ -599,6 +598,7 @@ private void importHDKey()
 
     /**
      * Reached after authentication has been provided
+     *
      * @return
      */
     private UpgradeKeyResult upgradeKey()
@@ -758,15 +758,15 @@ private boolean tryInitStrongBoxKey(KeyGenerator keyGenerator, String keyAddress
             keyGenerator.init(new KeyGenParameterSpec.Builder(
                     keyAddress,
                     KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
-                                      .setBlockModes(BLOCK_MODE)
-                                      .setKeySize(256)
-                                      .setUserAuthenticationRequired(useAuthentication)
-                                      .setIsStrongBoxBacked(true)
-                                      .setInvalidatedByBiometricEnrollment(false)
-                                      .setUserAuthenticationValidityDurationSeconds(AUTHENTICATION_DURATION_SECONDS)
-                                      .setRandomizedEncryptionRequired(true)
-                                      .setEncryptionPaddings(PADDING)
-                                      .build());
+                    .setBlockModes(BLOCK_MODE)
+                    .setKeySize(256)
+                    .setUserAuthenticationRequired(useAuthentication)
+                    .setIsStrongBoxBacked(true)
+                    .setInvalidatedByBiometricEnrollment(false)
+                    .setUserAuthenticationValidityDurationSeconds(AUTHENTICATION_DURATION_SECONDS)
+                    .setRandomizedEncryptionRequired(true)
+                    .setEncryptionPaddings(PADDING)
+                    .build());
 
             keyGenerator.generateKey();
         }
@@ -786,33 +786,17 @@ private boolean tryInitTEEKey(KeyGenerator keyGenerator, String keyAddress, bool
     {
         try
         {
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
-            {
-                keyGenerator.init(new KeyGenParameterSpec.Builder(
-                        keyAddress,
-                        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
-                        .setBlockModes(BLOCK_MODE)
-                        .setKeySize(256)
-                        .setUserAuthenticationRequired(useAuthentication)
-                        .setInvalidatedByBiometricEnrollment(false)
-                        .setUserAuthenticationValidityDurationSeconds(AUTHENTICATION_DURATION_SECONDS)
-                        .setRandomizedEncryptionRequired(true)
-                        .setEncryptionPaddings(PADDING)
-                        .build());
-            }
-            else
-            {
-                keyGenerator.init(new KeyGenParameterSpec.Builder(
-                        keyAddress,
-                        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
-                        .setBlockModes(BLOCK_MODE)
-                        .setKeySize(256)
-                        .setUserAuthenticationRequired(useAuthentication)
-                        .setUserAuthenticationValidityDurationSeconds(AUTHENTICATION_DURATION_SECONDS)
-                        .setRandomizedEncryptionRequired(true)
-                        .setEncryptionPaddings(PADDING)
-                        .build());
-            }
+            keyGenerator.init(new KeyGenParameterSpec.Builder(
+                    keyAddress,
+                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+                    .setBlockModes(BLOCK_MODE)
+                    .setKeySize(256)
+                    .setUserAuthenticationRequired(useAuthentication)
+                    .setInvalidatedByBiometricEnrollment(false)
+                    .setUserAuthenticationValidityDurationSeconds(AUTHENTICATION_DURATION_SECONDS)
+                    .setRandomizedEncryptionRequired(true)
+                    .setEncryptionPaddings(PADDING)
+                    .build());
         }
         catch (IllegalStateException | InvalidAlgorithmParameterException e)
         {
@@ -1262,11 +1246,13 @@ private boolean writeBytesToFile(String path, byte[] data)
 
     /**
      * Delete all traces of the key in Android keystore, encrypted bytes and iv file in private data area
+     *
      * @param keyAddress
      */
     synchronized void deleteKey(String keyAddress)
     {
-        try {
+        try
+        {
             KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
             keyStore.load(null);
             String matchingAddr = findMatchingAddrInKeyStore(keyAddress);
@@ -1276,7 +1262,9 @@ synchronized void deleteKey(String keyAddress)
             if (encryptedKeyBytes.exists()) encryptedKeyBytes.delete();
             if (encryptedBytesFileIV.exists()) encryptedBytesFileIV.delete();
             deleteAccount(matchingAddr);
-        } catch (Exception e) {
+        }
+        catch (Exception e)
+        {
             e.printStackTrace();
         }
     }
@@ -1284,21 +1272,21 @@ synchronized void deleteKey(String keyAddress)
     public void deleteAccount(String address) throws Exception
     {
         String cleanedAddr = Numeric.cleanHexPrefix(address).toLowerCase();
-            deleteAccountFiles(cleanedAddr);
+        deleteAccountFiles(cleanedAddr);
 
-            //Now delete database files (ie tokens, transactions and Tokenscript data for account)
-            File[] contents = context.getFilesDir().listFiles();
-            if (contents != null)
+        //Now delete database files (ie tokens, transactions and Tokenscript data for account)
+        File[] contents = context.getFilesDir().listFiles();
+        if (contents != null)
+        {
+            for (File f : contents)
             {
-                for (File f : contents)
+                String fileName = f.getName().toLowerCase();
+                if (fileName.contains(cleanedAddr.toLowerCase()))
                 {
-                    String fileName = f.getName().toLowerCase();
-                    if (fileName.contains(cleanedAddr.toLowerCase()))
-                    {
-                        deleteRecursive(f);
-                    }
+                    deleteRecursive(f);
                 }
             }
+        }
     }
 
     private void deleteAccountFiles(String address) throws Exception
@@ -1382,7 +1370,8 @@ private void vibrate()
         Vibrator vb = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
         if (vb != null && vb.hasVibrator())
         {
-            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
+            {
                 VibrationEffect vibe = VibrationEffect.createOneShot(200, DEFAULT_AMPLITUDE);
                 vb.vibrate(vibe);
             }
@@ -1403,7 +1392,7 @@ public boolean hasKeystore(String walletAddress)
             String matchingAddr = findMatchingAddrInKeyStore(walletAddress);
             return keyStore.containsAlias(matchingAddr);
         }
-        catch (KeyStoreException|NoSuchAlgorithmException|CertificateException|IOException e)
+        catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e)
         {
             Timber.e(e);
         }
diff --git a/app/src/main/java/com/alphawallet/app/ui/BaseFragment.java b/app/src/main/java/com/alphawallet/app/ui/BaseFragment.java
index c2c1a250f2..a4223bd16b 100644
--- a/app/src/main/java/com/alphawallet/app/ui/BaseFragment.java
+++ b/app/src/main/java/com/alphawallet/app/ui/BaseFragment.java
@@ -15,13 +15,14 @@
 
 import org.jetbrains.annotations.NotNull;
 
+import java.util.Arrays;
 import java.util.List;
 
 import dagger.hilt.android.AndroidEntryPoint;
 
 @AndroidEntryPoint
 public class BaseFragment extends Fragment implements Toolbar.OnMenuItemClickListener,
-    BackupTokenCallback
+        BackupTokenCallback
 {
     private Toolbar toolbar;
     private TextView toolbarTitle;
@@ -161,10 +162,6 @@ public void handleQRCode(int resultCode, Intent data, FragmentMessenger messenge
     {
     }
 
-    public void pinAuthorisation(boolean gotAuth)
-    {
-    }
-
     public void switchNetworkAndLoadUrl(long chainId, String url)
     {
     }
@@ -184,4 +181,10 @@ public void setImportFilename(String fName)
     public void backPressed()
     {
     }
+
+    protected boolean hasPermissionGranted(@NotNull String[] permissions, int[] grantResults, String permission)
+    {
+        int index = Arrays.asList(permissions).indexOf(permission);
+        return index != -1 && grantResults[index] != -1;
+    }
 }
diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java
index 4384727d6e..8e1ec130cc 100644
--- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java
+++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java
@@ -629,10 +629,6 @@ public void leaveFocus()
         stopBalanceListener();
     }
 
-    /**
-     * Used to expand or collapse the view
-     */
-
     private void addToBackStack(String nextFragment)
     {
         if (currentFragment != null && !currentFragment.equals(DAPP_BROWSER))
@@ -642,11 +638,6 @@ private void addToBackStack(String nextFragment)
         currentFragment = nextFragment;
     }
 
-    private void addToForwardStack(String prevFragment)
-    {
-        currentFragment = prevFragment;
-    }
-
     private void cancelSearchSession()
     {
         detachFragment(SEARCH);
@@ -1677,32 +1668,22 @@ private void requestCameraPermission(@NotNull PermissionRequest request)
     @Override
     public void gotCameraAccess(@NotNull String[] permissions, int[] grantResults)
     {
-        boolean cameraAccess = false;
-        for (int i = 0; i < permissions.length; i++)
+        boolean cameraAccess = hasPermissionGranted(permissions, grantResults, Manifest.permission.CAMERA);
+        if (cameraAccess)
         {
-            if (permissions[i].equals(Manifest.permission.CAMERA) && grantResults[i] != -1)
-            {
-                cameraAccess = true;
-                if (requestCallback != null)
-                    requestCallback.grant(requestCallback.getResources()); //now we can grant permission
-            }
+            if (requestCallback != null)
+                requestCallback.grant(requestCallback.getResources());
         }
-        if (!cameraAccess)
+        else
+        {
             Toast.makeText(getContext(), "Permission not given", Toast.LENGTH_SHORT).show();
+        }
     }
 
     @Override
     public void gotGeoAccess(@NotNull String[] permissions, int[] grantResults)
     {
-        boolean geoAccess = false;
-        for (int i = 0; i < permissions.length; i++)
-        {
-            if (permissions[i].equals(Manifest.permission.ACCESS_FINE_LOCATION) && grantResults[i] != -1)
-            {
-                geoAccess = true;
-                break;
-            }
-        }
+        boolean geoAccess = hasPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION);
         if (!geoAccess)
             Toast.makeText(getContext(), "Permission not given", Toast.LENGTH_SHORT).show();
         if (geoCallback != null && geoOrigin != null)
@@ -1712,16 +1693,7 @@ public void gotGeoAccess(@NotNull String[] permissions, int[] grantResults)
     @Override
     public void gotFileAccess(@NotNull String[] permissions, int[] grantResults)
     {
-        boolean fileAccess = false;
-        for (int i = 0; i < permissions.length; i++)
-        {
-            if (permissions[i].equals(Manifest.permission.READ_EXTERNAL_STORAGE) && grantResults[i] != -1)
-            {
-                fileAccess = true;
-                break;
-            }
-        }
-
+        boolean fileAccess = hasPermissionGranted(permissions, grantResults, Manifest.permission.READ_EXTERNAL_STORAGE);
         if (fileAccess) requestUpload();
     }
 
diff --git a/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java b/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java
index 374972574e..18689c4dda 100644
--- a/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java
+++ b/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java
@@ -17,7 +17,6 @@
 
 import android.content.Intent;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
@@ -190,21 +189,7 @@ private void initViewModel()
     private void initNotificationView(View view)
     {
         notificationView = view.findViewById(R.id.notification);
-        if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.M)
-        {
-            notificationView.setTitle(getContext().getString(R.string.title_version_support_warning));
-            notificationView.setMessage(getContext().getString(R.string.message_version_support_warning));
-            notificationView.setPrimaryButtonText(getContext().getString(R.string.hide_notification));
-            notificationView.setPrimaryButtonListener(() ->
-            {
-                notificationView.setVisibility(View.GONE);
-                viewModel.setMarshMallowWarning(true);
-            });
-        }
-        else
-        {
-            notificationView.setVisibility(View.GONE);
-        }
+        notificationView.setVisibility(View.GONE);
     }
 
     @Override
diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ActivityAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ActivityAdapter.java
index 919e7da648..a7c501935a 100644
--- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ActivityAdapter.java
+++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ActivityAdapter.java
@@ -42,12 +42,14 @@
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.IntStream;
 
 import timber.log.Timber;
 
 public class ActivityAdapter extends RecyclerView.Adapter<BinderViewHolder<?>> implements AdapterCallback
 {
-    private final ActivitySortedList<SortedItem<?>> items = new ActivitySortedList<>(SortedItem.class, new ActivitySortedList.Callback<SortedItem<?>>() {
+    private final ActivitySortedList<SortedItem<?>> items = new ActivitySortedList<>(SortedItem.class, new ActivitySortedList.Callback<SortedItem<?>>()
+    {
         @Override
         public int compare(SortedItem left, SortedItem right)
         {
@@ -55,32 +57,38 @@ public int compare(SortedItem left, SortedItem right)
         }
 
         @Override
-        public boolean areContentsTheSame(SortedItem oldItem, SortedItem newItem) {
+        public boolean areContentsTheSame(SortedItem oldItem, SortedItem newItem)
+        {
             return oldItem.areContentsTheSame(newItem);
         }
 
         @Override
-        public boolean areItemsTheSame(SortedItem left, SortedItem right) {
+        public boolean areItemsTheSame(SortedItem left, SortedItem right)
+        {
             return left.areItemsTheSame(right);
         }
 
         @Override
-        public void onChanged(int position, int count) {
+        public void onChanged(int position, int count)
+        {
             notifyItemRangeChanged(position, count);
         }
 
         @Override
-        public void onInserted(int position, int count) {
+        public void onInserted(int position, int count)
+        {
             notifyItemRangeInserted(position, count);
         }
 
         @Override
-        public void onRemoved(int position, int count) {
+        public void onRemoved(int position, int count)
+        {
             notifyItemRangeRemoved(position, count);
         }
 
         @Override
-        public void onMoved(int fromPosition, int toPosition) {
+        public void onMoved(int fromPosition, int toPosition)
+        {
             notifyItemMoved(fromPosition, toPosition);
         }
     });
@@ -97,7 +105,8 @@ public void onMoved(int fromPosition, int toPosition) {
     private boolean pendingReset = false;
 
     public ActivityAdapter(TokensService service, FetchTransactionsInteract fetchTransactionsInteract,
-                           AssetDefinitionService svs, ActivityDataInteract dataInteract) {
+                           AssetDefinitionService svs, ActivityDataInteract dataInteract)
+    {
         this.fetchTransactionsInteract = fetchTransactionsInteract;
         this.dataInteract = dataInteract;
         this.assetService = svs;
@@ -113,8 +122,10 @@ public ActivityAdapter(TokensService service, FetchTransactionsInteract fetchTra
     }
 
     @Override
-    public BinderViewHolder<?> onCreateViewHolder(ViewGroup parent, int viewType) {
-        switch (viewType) {
+    public BinderViewHolder<?> onCreateViewHolder(ViewGroup parent, int viewType)
+    {
+        switch (viewType)
+        {
             case TransactionHolder.VIEW_TYPE:
                 return new TransactionHolder(parent, tokensService, fetchTransactionsInteract,
                         assetService);
@@ -128,6 +139,9 @@ public BinderViewHolder<?> onCreateViewHolder(ViewGroup parent, int viewType) {
             case TransferHolder.VIEW_TYPE:
                 return new TransferHolder(parent, tokensService, fetchTransactionsInteract,
                         assetService);
+            default:
+                Timber.tag("ActivityAdapter").e("Wrong view type %s", viewType);
+                break;
         }
 
         return null;
@@ -153,7 +167,7 @@ else if (position > lastItemPos && dataInteract != null && System.currentTimeMil
 
     public void onRViewRecycled(RecyclerView.ViewHolder holder)
     {
-        onViewRecycled((BinderViewHolder<?>)(holder));
+        onViewRecycled((BinderViewHolder<?>) (holder));
     }
 
     @Override
@@ -185,16 +199,19 @@ private void fetchData(long earliestDate)
     };
 
     @Override
-    public int getItemCount() {
+    public int getItemCount()
+    {
         return items.size();
     }
 
     @Override
-    public int getItemViewType(int position) {
+    public int getItemViewType(int position)
+    {
         return items.get(position).viewType;
     }
 
-    public void setDefaultWallet(Wallet wallet) {
+    public void setDefaultWallet(Wallet wallet)
+    {
         this.wallet = wallet;
         notifyDataSetChanged();
     }
@@ -215,11 +232,11 @@ else if (obj instanceof EventSortedItem)
         }
         else if (obj instanceof DateSortedItem)
         {
-            return ((DateSortedItem)obj).getUID();
+            return ((DateSortedItem) obj).getUID();
         }
         else if (obj instanceof TransferSortedItem)
         {
-            return ((TransferSortedItem)obj).getUID();
+            return ((TransferSortedItem) obj).getUID();
         }
         else
         {
@@ -231,7 +248,7 @@ else if (obj instanceof TransferSortedItem)
 
     public void updateActivityItems(ActivityMeta[] activityItems)
     {
-        if (activityItems.length == 0) return ;
+        if (activityItems.length == 0) return;
 
         items.beginBatchedUpdates();
         if (itemLimit != 0)
@@ -243,17 +260,17 @@ public void updateActivityItems(ActivityMeta[] activityItems)
         {
             if (item instanceof TransactionMeta)
             {
-                TransactionSortedItem sortedItem = new TransactionSortedItem(TransactionHolder.VIEW_TYPE, (TransactionMeta)item, TimestampSortedItem.DESC);
+                TransactionSortedItem sortedItem = new TransactionSortedItem(TransactionHolder.VIEW_TYPE, (TransactionMeta) item, TimestampSortedItem.DESC);
                 items.addTransaction(sortedItem); //event has higher UI priority than an event, don't overwrite
             }
             else if (item instanceof EventMeta)
             {
-                EventSortedItem sortedItem = new EventSortedItem(EventHolder.VIEW_TYPE, (EventMeta)item, TimestampSortedItem.DESC);
+                EventSortedItem sortedItem = new EventSortedItem(EventHolder.VIEW_TYPE, (EventMeta) item, TimestampSortedItem.DESC);
                 items.add(sortedItem);
             }
             else if (item instanceof TokenTransferData)
             {
-                TransferSortedItem sortedItem = new TransferSortedItem(TransferHolder.VIEW_TYPE, (TokenTransferData)item, TimestampSortedItem.DESC);
+                TransferSortedItem sortedItem = new TransferSortedItem(TransferHolder.VIEW_TYPE, (TokenTransferData) item, TimestampSortedItem.DESC);
                 items.add(sortedItem);
             }
             items.add(DateSortedItem.round(item.getTimeStampSeconds()));
@@ -264,7 +281,8 @@ else if (item instanceof TokenTransferData)
         items.endBatchedUpdates();
     }
 
-    public void clear() {
+    public void clear()
+    {
         items.clear();
         notifyDataSetChanged();
     }
@@ -289,9 +307,9 @@ private void applyItemLimit()
             }
         }
 
-        if (items.get(items.size()-1) instanceof DateSortedItem)
+        if (items.get(items.size() - 1) instanceof DateSortedItem)
         {
-            removalObjects.add(items.get(items.size()-1));
+            removalObjects.add(items.get(items.size() - 1));
         }
 
         for (SortedItem sortedItem : removalObjects)
@@ -306,9 +324,9 @@ public void updateItems(List<ContractLocator> tokenContracts)
         for (int i = 0; i < items.size(); i++)
         {
             if (items.get(i).viewType == TransactionHolder.VIEW_TYPE
-                && items.get(i).value instanceof TransactionMeta)
+                    && items.get(i).value instanceof TransactionMeta)
             {
-                TransactionMeta tm = (TransactionMeta)items.get(i).value;
+                TransactionMeta tm = (TransactionMeta) items.get(i).value;
                 if (tm.contractAddress != null && hasMatchingContract(tokenContracts, tm.contractAddress.toLowerCase()))
                 {
                     notifyItemChanged(i);
@@ -352,26 +370,21 @@ public void resetRequired()
 
     public boolean isEmpty()
     {
-        for (int i = 0; i < items.size(); i++)
-        {
-            Object item = items.get(i).value;
-            if (item instanceof ActivityMeta)
-            {
-                return false;
-            }
-        }
-
-        return true;
+        return IntStream.range(0, items.size())
+                .noneMatch(i -> items.get(i).value instanceof ActivityMeta);
     }
 
-    private static class LabelHolder extends BinderViewHolder<Date> {
+    private static class LabelHolder extends BinderViewHolder<Date>
+    {
 
-        public LabelHolder(int resId, ViewGroup parent) {
+        public LabelHolder(int resId, ViewGroup parent)
+        {
             super(resId, parent);
         }
 
         @Override
-        public void bind(@Nullable Date data, @NonNull Bundle addition) {
+        public void bind(@Nullable Date data, @NonNull Bundle addition)
+        {
 
         }
     }
@@ -387,12 +400,13 @@ public void addTransaction(T item)
         {
             if (item instanceof TransactionSortedItem)
             {
-                TransactionSortedItem txSortedItem = (TransactionSortedItem)item;
+                TransactionSortedItem txSortedItem = (TransactionSortedItem) item;
                 int index = items.indexOf(txSortedItem);
                 if (index >= 0 && items.get(index).value instanceof EventMeta)
                 {
-                    EventMeta em = (EventMeta)items.get(index).value;
-                    if (!em.hash.equals(txSortedItem.value.hash)) add(item); //don't replace matching Event
+                    EventMeta em = (EventMeta) items.get(index).value;
+                    if (!em.hash.equals(txSortedItem.value.hash))
+                        add(item); //don't replace matching Event
                 }
                 else
                 {
@@ -411,7 +425,7 @@ public void onDestroy(RecyclerView recyclerView)
         //ensure all holders have their realm listeners cleaned up
         for (int childCount = recyclerView.getChildCount(), i = 0; i < childCount; ++i)
         {
-            ((BinderViewHolder<?>)recyclerView.getChildViewHolder(recyclerView.getChildAt(i))).onDestroyView();
+            ((BinderViewHolder<?>) recyclerView.getChildViewHolder(recyclerView.getChildAt(i))).onDestroyView();
         }
     }
 }
diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NodeStatusAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NodeStatusAdapter.java
index 59efcfd160..d02b2f47cc 100644
--- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NodeStatusAdapter.java
+++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NodeStatusAdapter.java
@@ -22,6 +22,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.IntStream;
 
 import io.reactivex.Single;
 import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -117,15 +118,9 @@ private NodeStatus fetchNodeStatus(long chainId)
     private void updateStatus(long chainId, NodeStatus status)
     {
         statusMap.put(chainId, status);
-        int position = 0;
-        for (int i=0; i<networkList.size(); i++)
-        {
-            if (networkList.get(i).chainId == chainId)
-            {
-                position = i;
-                break;
-            }
-        }
+        int position = IntStream.range(0, networkList.size())
+                .filter(i -> networkList.get(i).chainId == chainId)
+                .findFirst().orElse(0);
         notifyItemChanged(position);
         Timber.d("updateStatus: chain: %s-%s: %s", chainId, EthereumNetworkBase.getShortChainName(chainId),status);
     }
diff --git a/app/src/main/java/com/alphawallet/app/util/LocaleUtils.java b/app/src/main/java/com/alphawallet/app/util/LocaleUtils.java
index 63fc3551b1..c57014c8c3 100644
--- a/app/src/main/java/com/alphawallet/app/util/LocaleUtils.java
+++ b/app/src/main/java/com/alphawallet/app/util/LocaleUtils.java
@@ -6,7 +6,6 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.os.Build;
 import android.os.LocaleList;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
@@ -115,40 +114,16 @@ private static String getActiveLocaleName(Context context)
      * @return String as a Language Locale
      */
     public static String getDeviceSettingsLocale(Context context) {
-        String locale;
-
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
-        {
-            locale = context.getResources().getConfiguration().getLocales().get(0).getLanguage();
-        }
-        else
-        {
-            locale = context.getResources().getConfiguration().locale.getLanguage();
-        }
-        return locale;
+        return context.getResources().getConfiguration().getLocales().get(0).getLanguage();
     }
 
     private static String getCurrentLanguage()
     {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
-        {
-            return LocaleList.getDefault().get(0).getLanguage();
-        }
-        else
-        {
-            return Locale.getDefault().getLanguage();
-        }
+        return LocaleList.getDefault().get(0).getLanguage();
     }
 
     private static String getCurrentCountry()
     {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
-        {
-            return LocaleList.getDefault().get(0).getCountry();
-        }
-        else
-        {
-            return Locale.getDefault().getCountry();
-        }
+        return LocaleList.getDefault().get(0).getCountry();
     }
 }
diff --git a/app/src/main/java/com/alphawallet/app/web3/Web3View.java b/app/src/main/java/com/alphawallet/app/web3/Web3View.java
index 91f774f712..8fa6a1d915 100644
--- a/app/src/main/java/com/alphawallet/app/web3/Web3View.java
+++ b/app/src/main/java/com/alphawallet/app/web3/Web3View.java
@@ -1,13 +1,8 @@
 package com.alphawallet.app.web3;
 
-import static androidx.webkit.WebSettingsCompat.FORCE_DARK_OFF;
-import static androidx.webkit.WebSettingsCompat.FORCE_DARK_ON;
-
 import android.annotation.SuppressLint;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.graphics.Bitmap;
-import android.os.Build;
 import android.util.AttributeSet;
 import android.webkit.WebChromeClient;
 import android.webkit.WebResourceError;
@@ -18,9 +13,6 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.webkit.WebSettingsCompat;
-import androidx.webkit.WebViewFeature;
 
 import com.alphawallet.app.BuildConfig;
 import com.alphawallet.app.entity.URLLoadInterface;
@@ -377,15 +369,6 @@ else if (!loadingError && loadInterface != null)
             loadingError = false;
         }
 
-        @Override
-        public boolean shouldOverrideUrlLoading(WebView view, String url)
-        {
-            redirect = true;
-
-            return externalClient.shouldOverrideUrlLoading(view, url)
-                    || internalClient.shouldOverrideUrlLoading(view, url);
-        }
-
         @Override
         public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)
         {
@@ -394,7 +377,6 @@ public void onReceivedError(WebView view, WebResourceRequest request, WebResourc
                 externalClient.onReceivedError(view, request, error);
         }
 
-        @RequiresApi(api = Build.VERSION_CODES.N)
         @Override
         public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
         {
diff --git a/app/src/test/java/com/alphawallet/app/entity/ContractLocatorTest.java b/app/src/test/java/com/alphawallet/app/entity/ContractLocatorTest.java
new file mode 100644
index 0000000000..e2d11dc23d
--- /dev/null
+++ b/app/src/test/java/com/alphawallet/app/entity/ContractLocatorTest.java
@@ -0,0 +1,23 @@
+package com.alphawallet.app.entity;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+import org.junit.Test;
+
+public class ContractLocatorTest
+{
+    @Test
+    public void should_from_addresses()
+    {
+        String[] addresses = {"add1", "add2"};
+
+        ContractLocator[] contractLocators = ContractLocator.fromAddresses(addresses, 1L);
+
+        assertThat(contractLocators.length, equalTo(2));
+        assertThat(contractLocators[0].address, equalTo("add1"));
+        assertThat(contractLocators[0].chainId, equalTo(1L));
+        assertThat(contractLocators[1].address, equalTo("add2"));
+        assertThat(contractLocators[1].chainId, equalTo(1L));
+    }
+}
\ No newline at end of file
diff --git a/app/src/test/java/com/alphawallet/app/entity/tokens/TicketTest.java b/app/src/test/java/com/alphawallet/app/entity/tokens/TicketTest.java
new file mode 100644
index 0000000000..6722b03ef7
--- /dev/null
+++ b/app/src/test/java/com/alphawallet/app/entity/tokens/TicketTest.java
@@ -0,0 +1,23 @@
+package com.alphawallet.app.entity.tokens;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+import org.junit.Test;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
+
+public class TicketTest
+{
+    @Test
+    public void should_get_token_count()
+    {
+        Ticket ticket = new Ticket(null, Arrays.asList(BigInteger.valueOf(2), BigInteger.ZERO, BigInteger.ONE), 0L, null, null);
+        assertThat(ticket.getTokenCount(), equalTo(2));
+
+        ticket = new Ticket(null, (List<BigInteger>) null, 0L, null, null);
+        assertThat(ticket.getTokenCount(), equalTo(0));
+    }
+}
diff --git a/app/src/test/java/com/alphawallet/app/ui/widget/adapter/ActivityAdapterTest.java b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/ActivityAdapterTest.java
new file mode 100644
index 0000000000..1139a04e9f
--- /dev/null
+++ b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/ActivityAdapterTest.java
@@ -0,0 +1,34 @@
+package com.alphawallet.app.ui.widget.adapter;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.alphawallet.app.entity.ActivityMeta;
+import com.alphawallet.app.entity.EventMeta;
+import com.alphawallet.shadows.ShadowAnalyticsService;
+import com.alphawallet.shadows.ShadowApp;
+import com.alphawallet.shadows.ShadowKeyProviderFactory;
+import com.alphawallet.shadows.ShadowKeyService;
+import com.alphawallet.shadows.ShadowRealmManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowPackageManager;
+
+@RunWith(AndroidJUnit4.class)
+@Config(shadows = {ShadowApp.class, ShadowKeyProviderFactory.class, ShadowRealmManager.class, ShadowKeyService.class, ShadowAnalyticsService.class, ShadowPackageManager.class})
+public class ActivityAdapterTest
+{
+    @Test
+    public void test_isEmpty()
+    {
+        ActivityAdapter activityAdapter = new ActivityAdapter(null, null, null);
+        activityAdapter.updateActivityItems(new ActivityMeta[]{});
+        assertThat(activityAdapter.isEmpty(), equalTo(true));
+        activityAdapter.updateActivityItems(new ActivityMeta[]{ new EventMeta("", "", "", System.currentTimeMillis(), 1L)});
+        assertThat(activityAdapter.isEmpty(), equalTo(false));
+    }
+}
diff --git a/lib/build.gradle b/lib/build.gradle
index d368921cb8..ba8249bfed 100644
--- a/lib/build.gradle
+++ b/lib/build.gradle
@@ -11,10 +11,6 @@ apply plugin: 'com.github.johnrengelman.shadow'
 apply plugin: 'java-library'
 
 dependencies {
-    implementation files('..\\app\\libs\\abi-4.8.8-android.jar')
-    implementation files('..\\app\\libs\\core-4.8.8-android.jar')
-    implementation files('..\\app\\libs\\crypto-4.8.8-android.jar')
-    implementation files('..\\app\\libs\\utils-4.8.8-android.jar')
     testImplementation 'junit:junit:4.13.2'
     implementation 'org.bouncycastle:bcprov-jdk15on:1.62'
     // https://mvnrepository.com/artifact/com.github.cliftonlabs/json-simple
diff --git a/lib/src/main/java/com/alphawallet/token/entity/EthereumReadBuffer.java b/lib/src/main/java/com/alphawallet/token/entity/EthereumReadBuffer.java
index 2582c1aec7..6321d538d9 100644
--- a/lib/src/main/java/com/alphawallet/token/entity/EthereumReadBuffer.java
+++ b/lib/src/main/java/com/alphawallet/token/entity/EthereumReadBuffer.java
@@ -6,6 +6,7 @@
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import com.alphawallet.token.tools.Numeric;
 
@@ -35,6 +36,7 @@ public BigInteger readBI() throws IOException
 
     /**
      * Custom BigInteger which is formed from a byte array of sz size.
+     *
      * @param sz size of bytes to read for the BigInteger
      * @return
      * @throws IOException
@@ -50,7 +52,8 @@ public BigInteger readBI(int sz) throws IOException
         return retVal;
     }
 
-    public String readAddress() throws IOException {
+    public String readAddress() throws IOException
+    {
         byte[] buffer20 = new byte[20];
         read(buffer20);
         return Numeric.toHexString(buffer20);
@@ -68,9 +71,12 @@ public int available() throws IOException
 
     public void readSignature(byte[] signature) throws IOException
     {
-        if (signature.length == 65) {
+        if (signature.length == 65)
+        {
             read(signature); // would it throw already, if the data is too short? - Weiwu
-        } else {
+        }
+        else
+        {
             throw new IOException("Data isn't a signature"); // Is this even necessary? - Weiwu
         }
     }
@@ -91,7 +97,8 @@ public void readUnsignedShort(int[] ints) throws IOException
     /*
      * equivalent of Short.toUnsignedInt
      */
-    private int toUnsignedInt(short s) {
+    private int toUnsignedInt(short s)
+    {
         return s & 0x0000FFFF;
     }
 
@@ -106,7 +113,8 @@ private int toUnsignedInt(byte b)
     /*
      * equivalent of Integer.readUnsignedLong
      */
-    public long toUnsignedLong(int i) {
+    public long toUnsignedLong(int i)
+    {
         return i & 0x00000000ffffffffL; // long is always 64 bits
     }
 
@@ -163,10 +171,9 @@ public int[] readCompressedIndices(int indiciesLength) throws IOException
             index++;
         }
 
-        int[] indexArray = new int[indexList.size()];
-        for (int i = 0; i < indexList.size(); i++) indexArray[i] = indexList.get(i);
-
-        return indexArray;
+        return indexList.stream()
+                .mapToInt(Integer::intValue)
+                .toArray();
     }
 
     public byte[] readBytes(int i) throws IOException