diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/BitcoinAddressValidator.java b/app/src/main/java/com/m2049r/xmrwallet/util/BitcoinAddressValidator.java
index 5d1dda91..76fa8979 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/util/BitcoinAddressValidator.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/util/BitcoinAddressValidator.java
@@ -16,12 +16,13 @@
 
 package com.m2049r.xmrwallet.util;
 
-// based on https://rosettacode.org/wiki/Bitcoin/address_validation#Java
+// mostly based on https://rosettacode.org/wiki/Bitcoin/address_validation#Java
 
 import com.m2049r.xmrwallet.model.NetworkType;
 import com.m2049r.xmrwallet.model.WalletManager;
 
 import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
@@ -31,8 +32,9 @@ public class BitcoinAddressValidator {
     private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
 
     public static boolean validate(String addrress) {
-        return validate(addrress,
-                WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet);
+        boolean testnet = WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet;
+        if (validate(addrress, testnet)) return true;
+        return validateBech32Segwit(addrress, testnet);
     }
 
     public static boolean validate(String addrress, boolean testnet) {
@@ -85,4 +87,112 @@ public class BitcoinAddressValidator {
             throw new IllegalStateException(e);
         }
     }
+
+    //
+    // validate Bech32 segwit
+    // see https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki for spec
+    //
+
+    private static final String DATA_CHARS = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
+
+    public static boolean validateBech32Segwit(String bech32, boolean testnet) {
+        if (!bech32.equals(bech32.toLowerCase()) && !bech32.equals(bech32.toUpperCase())) {
+            return false; // mixing upper and lower case not allowed
+        }
+        bech32 = bech32.toLowerCase();
+
+        if (testnet && !bech32.startsWith("tb1")) return false;
+        if (!testnet && !bech32.startsWith("bc1")) return false;
+
+        if ((bech32.length() < 14) || (bech32.length() > 74)) return false;
+        int mod = bech32.length() % 8;
+        if ((mod == 0) || (mod == 3) || (mod == 5)) return false;
+
+        int sep = -1;
+        final byte[] bytes = bech32.getBytes(StandardCharsets.US_ASCII);
+        for (int i = 0; i < bytes.length; i++) {
+            if ((bytes[i] < 33) || (bytes[i] > 126)) {
+                return false;
+            }
+            if (bytes[i] == 49) sep = i; // 49 := '1' in ASCII
+        }
+
+        if (sep != 2) return false; // bech32 always has len(hrp)==2
+        if (sep > bytes.length - 7) {
+            return false; // min 6 bytes data
+        }
+        if (bytes.length < 8) { // hrp{min}=1 + sep=1 + data{min}=6 := 8
+            return false; // too short
+        }
+        if (bytes.length > 90) {
+            return false; // too long
+        }
+
+        final byte[] hrp = Arrays.copyOfRange(bytes, 0, sep);
+
+        final byte[] data = Arrays.copyOfRange(bytes, sep + 1, bytes.length);
+        for (int i = 0; i < data.length; i++) {
+            int b = DATA_CHARS.indexOf(data[i]);
+            if (b < 0) return false; // invalid character
+            data[i] = (byte) b;
+        }
+
+        if (!validateBech32Data(data)) return false;
+
+        return verifyChecksum(hrp, data);
+    }
+
+    private static int polymod(byte[] values) {
+        final int[] GEN = {0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3};
+        int chk = 1;
+        for (byte v : values) {
+            byte b = (byte) (chk >> 25);
+            chk = ((chk & 0x1ffffff) << 5) ^ v;
+            for (int i = 0; i < 5; i++) {
+                chk ^= ((b >> i) & 1) == 1 ? GEN[i] : 0;
+            }
+        }
+        return chk;
+    }
+
+    private static byte[] hrpExpand(byte[] hrp) {
+        final byte[] expanded = new byte[(2 * hrp.length) + 1];
+        int i = 0;
+        for (int j = 0; j < hrp.length; j++) {
+            expanded[i++] = (byte) (hrp[j] >> 5);
+        }
+        expanded[i++] = 0;
+        for (int j = 0; j < hrp.length; j++) {
+            expanded[i++] = (byte) (hrp[j] & 0x1f);
+        }
+        return expanded;
+    }
+
+    private static boolean verifyChecksum(byte[] hrp, byte[] data) {
+        final byte[] hrpExpanded = hrpExpand(hrp);
+        final byte[] values = new byte[hrpExpanded.length + data.length];
+        System.arraycopy(hrpExpanded, 0, values, 0, hrpExpanded.length);
+        System.arraycopy(data, 0, values, hrpExpanded.length, data.length);
+        return (polymod(values) == 1);
+    }
+
+    private static boolean validateBech32Data(final byte[] data) {
+        if ((data[0] < 0) || (data[0] > 16)) return false; // witness version
+        final int programLength = data.length - 1 - 6; // 1-byte version at beginning & 6-byte checksum at end
+
+        // since we are coming from our own decoder, we don't need to verify data is 5-bit bytes
+
+        final int convertedSize = programLength * 5 / 8;
+        final int remainderSize = programLength * 5 % 8;
+
+        if ((convertedSize < 2) || (convertedSize > 40)) return false;
+
+        if ((data[0] == 0) && (convertedSize != 20) && (convertedSize != 32)) return false;
+
+        if (remainderSize >= 5) return false;
+        // ignore checksum at end and get last byte of program
+        if ((data[data.length - 1 - 6] & ((1 << remainderSize) - 1)) != 0) return false;
+
+        return true;
+    }
 }
\ No newline at end of file
diff --git a/app/src/test/java/com/m2049r/xmrwallet/util/BitcoinAddressValidatorTest.java b/app/src/test/java/com/m2049r/xmrwallet/util/BitcoinAddressValidatorTest.java
index 5882723f..c2502fb4 100644
--- a/app/src/test/java/com/m2049r/xmrwallet/util/BitcoinAddressValidatorTest.java
+++ b/app/src/test/java/com/m2049r/xmrwallet/util/BitcoinAddressValidatorTest.java
@@ -18,6 +18,7 @@ package com.m2049r.xmrwallet.util;
 
 import org.junit.Test;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 
@@ -54,4 +55,38 @@ public class BitcoinAddressValidatorTest {
         assertTrue(!BitcoinAddressValidator.validate("3NagLCvw8fLwtoUrK7s2mJPy9k6hoyWvTU ", false));
         assertTrue(!BitcoinAddressValidator.validate(" 3NagLCvw8fLwtoUrK7s2mJPy9k6hoyWvTU ", false));
     }
+
+    @Test
+    public void validSegwit() {
+        // see https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", false));
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx", true));
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3", false));
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", true));
+
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", false));
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", true));
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx", false));
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("BC1SW50QA3JX3S", false));
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", false));
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy", true));
+
+        assertTrue(BitcoinAddressValidator.validateBech32Segwit("bc1q76awjp3nmklgnf0yyu0qncsekktf4e3qj248t4", false)); // electrum blog
+
+    }
+
+    @Test
+    public void invalidSegwit() {
+        // see https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
+        assertFalse(BitcoinAddressValidator.validateBech32Segwit("tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty", true)); // Invalid human-readable part
+        assertFalse(BitcoinAddressValidator.validateBech32Segwit("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", true)); // Invalid checksum
+        assertFalse(BitcoinAddressValidator.validateBech32Segwit("BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2", true)); // Invalid witness version
+        assertFalse(BitcoinAddressValidator.validateBech32Segwit("bc1rw5uspcuh", true)); // Invalid program length
+        assertFalse(BitcoinAddressValidator.validateBech32Segwit("bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90", true)); // Invalid program length
+        assertFalse(BitcoinAddressValidator.validateBech32Segwit("BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P", true)); // Invalid program length for witness version 0 (per BIP141)
+        assertFalse(BitcoinAddressValidator.validateBech32Segwit("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7", true)); // Mixed case
+        assertFalse(BitcoinAddressValidator.validateBech32Segwit("bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du", true)); // zero padding of more than 4 bits
+        assertFalse(BitcoinAddressValidator.validateBech32Segwit("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv", true)); // Non-zero padding in 8-to-5 conversion
+        assertFalse(BitcoinAddressValidator.validateBech32Segwit("bc1gmk9yu", true)); // Empty data section
+    }
 }