Detailed changes
  
  
    
    @@ -0,0 +1,22 @@
+<vector android:height="24dp" android:viewportHeight="1277.38"
+    android:viewportWidth="1277.38" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"
+    android:tint="?attr/colorControlNormal">
+    <path android:fillAlpha="0.45" android:fillColor="@android:color/white"
+        android:fillType="nonZero"
+        android:pathData="M638.58,472.33l0,-472.33l-392.07,650.54l392.07,231.75z" android:strokeAlpha="0.45"/>
+    <path android:fillAlpha="0.796" android:fillColor="@android:color/white"
+        android:fillType="nonZero"
+        android:pathData="M638.58,882.29l392.06,-231.75l-392.06,-650.54l-8.57,29.11l0,844.63z" android:strokeAlpha="0.796"/>
+    <path android:fillAlpha="0.764" android:fillColor="@android:color/white"
+        android:fillType="nonZero"
+        android:pathData="M638.58,1277.38l392.3,-552.49l-392.3,231.63l-4.83,5.89l0,300.87z" android:strokeAlpha="0.764"/>
+    <path android:fillAlpha="0.45" android:fillColor="@android:color/white"
+        android:fillType="nonZero"
+        android:pathData="M246.51,724.89l392.07,552.49l0,-320.86z" android:strokeAlpha="0.45"/>
+    <path android:fillAlpha="0.92" android:fillColor="@android:color/white"
+        android:fillType="nonZero"
+        android:pathData="M638.58,472.33l0,409.96l392.06,-231.75z" android:strokeAlpha="0.92"/>
+    <path android:fillAlpha="0.776" android:fillColor="@android:color/white"
+        android:fillType="nonZero"
+        android:pathData="M638.58,472.33l-392.07,178.21l392.07,231.75z" android:strokeAlpha="0.776"/>
+</vector>
  
  
  
    
    @@ -1429,7 +1429,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
     public synchronized Uri wholeIsKnownURI() {
         if (wholeIsKnownURI != null) return wholeIsKnownURI;
 
-        if (Patterns.BITCOIN_URI.matcher(body).matches() ||Patterns.BITCOINCASH_URI.matcher(body).matches() || Patterns.MONERO_URI.matcher(body).matches() || Patterns.WOWNERO_URI.matcher(body).matches()) {
+        if (Patterns.BITCOIN_URI.matcher(body).matches() ||Patterns.BITCOINCASH_URI.matcher(body).matches() || Patterns.ETHEREUM_URI.matcher(body).matches() || Patterns.MONERO_URI.matcher(body).matches() || Patterns.WOWNERO_URI.matcher(body).matches()) {
             wholeIsKnownURI = Uri.parse(body.replace(":", "://")); // hack to make query parser work
         }
 
  
  
  
    
    @@ -827,6 +827,10 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
                     binding.command.setText(uri.getSchemeSpecificPart());
                     binding.command.setCompoundDrawablesRelativeWithIntrinsicBounds(getDrawable(R.drawable.bitcoin_cash_24dp), null, null, null);
                     binding.command.setCompoundDrawablePadding(20);
+                } else if (uri.getScheme().equals("ethereum")) {
+                    binding.command.setText(uri.getSchemeSpecificPart());
+                    binding.command.setCompoundDrawablesRelativeWithIntrinsicBounds(getDrawable(R.drawable.eth_24dp), null, null, null);
+                    binding.command.setCompoundDrawablePadding(20);
                 } else if (uri.getScheme().equals("monero")) {
                     binding.command.setText(uri.getSchemeSpecificPart());
                     binding.command.setCompoundDrawablesRelativeWithIntrinsicBounds(getDrawable(R.drawable.monero_24dp), null, null, null);
  
  
  
    
    @@ -943,6 +943,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
             final var formattedAmount = amount == null || amount.equals("") ? "" : amount + " ";
             viewHolder.download_button.setIconResource(R.drawable.bitcoin_cash_24dp);
             viewHolder.download_button.setText("Send " + formattedAmount + "Bitcoin Cash");
+        } else if ("ethereum".equals(uri.getScheme())) {
+            final var amount = uri.getQueryParameter("value");
+            final var formattedAmount = amount == null || amount.equals("") ? "" : amount + " ";
+            viewHolder.download_button.setIconResource(R.drawable.eth_24dp);
+            viewHolder.download_button.setText("Send " + formattedAmount + "via Ethereum");
         } else if ("monero".equals(uri.getScheme())) {
             final var amount = uri.getQueryParameter("tx_amount");
             final var formattedAmount = amount == null || amount.equals("") ? "" : amount + " ";
  
  
  
    
    @@ -134,6 +134,7 @@ public class MyLinkify {
         Linkify.addLinks(body, Patterns.SMS_URI, "sms");
         Linkify.addLinks(body, Patterns.BITCOIN_URI, "bitcoin");
         Linkify.addLinks(body, Patterns.BITCOINCASH_URI, "bitcoincash");
+        Linkify.addLinks(body, Patterns.ETHEREUM_URI, "ethereum");
         Linkify.addLinks(body, Patterns.MONERO_URI, "monero");
         Linkify.addLinks(body, Patterns.WOWNERO_URI, "wownero");
         Linkify.addLinks(body, Patterns.AUTOLINK_WEB_URL, "http", WEBURL_MATCH_FILTER, WEBURL_TRANSFORM_FILTER);
  
  
  
    
    @@ -45,6 +45,15 @@ public class Patterns {
                     + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])"
                     + "|(?:\\%[a-fA-F0-9]{2}))+)?");
 
+    public static final Pattern ETHEREUM_URI = Pattern
+            .compile("ethereum\\:(?:pay\\-)?(0x[0-9a-f]{40})(?:@[0-9]+)?(?:/(?:(?:["
+                    + Patterns.GOOD_IRI_CHAR
+                    + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])"
+                    + "|(?:\\%[a-fA-F0-9]{2}))+)?(?:\\?(?:(?:["
+                    + Patterns.GOOD_IRI_CHAR
+                    + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])"
+                    + "|(?:\\%[a-fA-F0-9]{2}))+)?");
+
     public static final Pattern MONERO_URI = Pattern
             .compile("monero\\:(?:[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93})(?:\\?(?:(?:["
                     + Patterns.GOOD_IRI_CHAR