diff --git a/lib/protobuf-decoder/hexUtils.js b/lib/protobuf-decoder/hexUtils.js
new file mode 100644
index 0000000..6f6ff52
--- /dev/null
+++ b/lib/protobuf-decoder/hexUtils.js
@@ -0,0 +1,36 @@
+import { Buffer } from 'buffer'
+
+export function parseInput(input) {
+  const normalizedInput = input.replace(/\s/g, "");
+  const normalizedHexInput = normalizedInput.replace(/0x/g, "").toLowerCase();
+  if (isHex(normalizedHexInput)) {
+    return Buffer.from(normalizedHexInput, "hex");
+  } else {
+    return Buffer.from(normalizedInput, "base64");
+  }
+}
+
+export function isHex(string) {
+  let result = true;
+  for (const char of string) {
+    if (!((char >= "a" && char <= "f") || (char >= "0" && char <= "9"))) {
+      result = false;
+    }
+  }
+  return result;
+}
+
+export function bufferLeToBeHex(buffer) {
+  let output = "";
+  for (const v of buffer) {
+    const hex = v.toString(16);
+    if (hex.length === 1) {
+      output = "0" + hex + output;
+    } else {
+      output = hex + output;
+    }
+  }
+  return output;
+}
+
+export const bufferToPrettyHex = b => [...b].map(c => c.toString(16).padStart(2, '0')).join(' ');
diff --git a/lib/protobuf-decoder/intUtils.js b/lib/protobuf-decoder/intUtils.js
new file mode 100644
index 0000000..3e16ea4
--- /dev/null
+++ b/lib/protobuf-decoder/intUtils.js
@@ -0,0 +1,27 @@
+import JSBI from "jsbi";
+
+export function interpretAsSignedType(n) {
+  // see https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/wire_format_lite.h#L857-L876
+  // however, this is a simpler equivalent formula
+  const isEven = JSBI.equal(JSBI.bitwiseAnd(n, JSBI.BigInt(1)), JSBI.BigInt(0));
+  if (isEven) {
+    return JSBI.divide(n, JSBI.BigInt(2));
+  } else {
+    return JSBI.multiply(
+      JSBI.BigInt(-1),
+      JSBI.divide(JSBI.add(n, JSBI.BigInt(1)), JSBI.BigInt(2))
+    );
+  }
+}
+
+export function interpretAsTwosComplement(n, bits) {
+  const isTwosComplement = JSBI.equal(
+    JSBI.signedRightShift(n, JSBI.BigInt(bits - 1)),
+    JSBI.BigInt(1)
+  );
+  if (isTwosComplement) {
+    return JSBI.subtract(n, JSBI.leftShift(JSBI.BigInt(1), JSBI.BigInt(bits)));
+  } else {
+    return n;
+  }
+}
diff --git a/lib/protobuf-decoder/protobufDecoder.js b/lib/protobuf-decoder/protobufDecoder.js
new file mode 100644
index 0000000..f9a11af
--- /dev/null
+++ b/lib/protobuf-decoder/protobufDecoder.js
@@ -0,0 +1,132 @@
+import { decodeVarint } from "./varintUtils";
+
+class BufferReader {
+  constructor(buffer) {
+    this.buffer = buffer;
+    this.offset = 0;
+  }
+
+  readVarInt() {
+    const result = decodeVarint(this.buffer, this.offset);
+    this.offset += result.length;
+
+    return result.value;
+  }
+
+  readBuffer(length) {
+    this.checkByte(length);
+    const result = this.buffer.slice(this.offset, this.offset + length);
+    this.offset += length;
+
+    return result;
+  }
+
+  // gRPC has some additional header - remove it
+  trySkipGrpcHeader() {
+    const backupOffset = this.offset;
+
+    if (this.buffer[this.offset] === 0 && this.leftBytes() >= 5) {
+      this.offset++;
+      const length = this.buffer.readInt32BE(this.offset);
+      this.offset += 4;
+
+      if (length > this.leftBytes()) {
+        // Something is wrong, revert
+        this.offset = backupOffset;
+      }
+    }
+  }
+
+  leftBytes() {
+    return this.buffer.length - this.offset;
+  }
+
+  checkByte(length) {
+    const bytesAvailable = this.leftBytes();
+    if (length > bytesAvailable) {
+      throw new Error(
+        "Not enough bytes left. Requested: " +
+          length +
+          " left: " +
+          bytesAvailable
+      );
+    }
+  }
+
+  checkpoint() {
+    this.savedOffset = this.offset;
+  }
+
+  resetToCheckpoint() {
+    this.offset = this.savedOffset;
+  }
+}
+
+export const TYPES = {
+  VARINT: 0,
+  FIXED64: 1,
+  LENDELIM: 2,
+  FIXED32: 5
+};
+
+export function decodeProto(buffer) {
+  const reader = new BufferReader(buffer);
+  const parts = [];
+
+  reader.trySkipGrpcHeader();
+
+  try {
+    while (reader.leftBytes() > 0) {
+      reader.checkpoint();
+
+      const byteRange = [reader.offset];
+      const indexType = parseInt(reader.readVarInt().toString());
+      const type = indexType & 0b111;
+      const index = indexType >> 3;
+
+      let value;
+      if (type === TYPES.VARINT) {
+        value = reader.readVarInt().toString();
+      } else if (type === TYPES.LENDELIM) {
+        const length = parseInt(reader.readVarInt().toString());
+        value = reader.readBuffer(length);
+      } else if (type === TYPES.FIXED32) {
+        value = reader.readBuffer(4);
+      } else if (type === TYPES.FIXED64) {
+        value = reader.readBuffer(8);
+      } else {
+        throw new Error("Unknown type: " + type);
+      }
+      byteRange.push(reader.offset);
+
+      parts.push({
+        byteRange,
+        index,
+        type,
+        value
+      });
+    }
+  } catch (err) {
+    reader.resetToCheckpoint();
+  }
+
+  return {
+    parts,
+    leftOver: reader.readBuffer(reader.leftBytes())
+  };
+}
+
+export function typeToString(type, subType) {
+  switch (type) {
+    case TYPES.VARINT:
+      return "varint";
+    case TYPES.LENDELIM:
+      return subType || "len_delim";
+    case TYPES.FIXED32:
+      return "fixed32";
+    case TYPES.FIXED64:
+      return "fixed64";
+    default:
+      return "unknown";
+  }
+}
diff --git a/lib/protobuf-decoder/varintUtils.js b/lib/protobuf-decoder/varintUtils.js
new file mode 100644
index 0000000..ceae6f5
--- /dev/null
+++ b/lib/protobuf-decoder/varintUtils.js
@@ -0,0 +1,24 @@
+"use bigint"
+export function decodeVarint(buffer, offset) {
+  let res = BigInt(0);
+  let shift = 0;
+  let byte = 0;
+
+  do {
+    if (offset >= buffer.length) {
+      throw new RangeError("Index out of bound decoding varint");
+    }
+
+    byte = buffer[offset++];
+
+    const multiplier = exponentiate(BigInt(2), BigInt(shift));
+    const thisByteValue = multiply(BigInt(byte & 0x7f), multiplier);
+    shift += 7;
+    res = add(res, thisByteValue);
+  } while (byte >= 0x80);
+
+  return {
+    value: res,
+    length: shift / 7
+  };
+}
diff --git a/lib/totp-quickjs/base32decoder.js b/lib/totp-quickjs/base32decoder.js
index b74d251..7c0e514 100644
--- a/lib/totp-quickjs/base32decoder.js
+++ b/lib/totp-quickjs/base32decoder.js
@@ -23,4 +23,24 @@ function leftpad(str, len, pad) {
 			(str = new Array(len + 1 - str.length).join(pad) + str),
 		str
 	);
+}
+
+export function base64decode(base64String) {    
+        var sliceSize = 1024;
+        var byteCharacters = window.atob(base64String);
+        var bytesLength = byteCharacters.length;
+        var slicesCount = Math.ceil(bytesLength / sliceSize);
+        var byteArrays = new Array(slicesCount);
+
+        for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
+            var begin = sliceIndex * sliceSize;
+            var end = Math.min(begin + sliceSize, bytesLength);
+
+            var bytes = new Array(end - begin);
+            for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
+                bytes[i] = byteCharacters[offset].charCodeAt(0);
+            }
+            byteArrays[sliceIndex] = new Uint8Array(bytes);
+        }
+        return byteArrays
 }
\ No newline at end of file
diff --git a/setting/utils/queryParser.js b/setting/utils/queryParser.js
index 985dcde..8bb2365 100644
--- a/setting/utils/queryParser.js
+++ b/setting/utils/queryParser.js
@@ -1,10 +1,29 @@
+import { decodeProto } from "../../lib/protobuf-decoder/protobufDecoder";
 import { TOTP } from "../../lib/totp-quickjs";
+import { base64decode } from "../../lib/totp-quickjs/base32decoder";
 
-const otpScheme = "otpauth:/";
+const otpauthScheme = "otpauth:/";
+const googleMigrationScheme = "otpauth-migration:/";
 
 export function getTOTPByLink(link) {
+	if(link.includes(otpauthScheme))
+		return getByOtpauthScheme(link)
+	if(link.includes(googleMigrationScheme))
+		return getByGoogleMigrationScheme(link)
+
+	return null;
+}
+
+function getHashType(algorithm) {
+	if (algorithm == "SHA1") return "SHA-1";
+	if (algorithm == "SHA256") return "SHA-256";
+	if (algorithm == "SHA512") return "SHA-512";
+	else return "SHA-1";
+}
+
+function getByOtpauthScheme(link){
 	try {
-		let args = link.split("/", otpScheme.length);
+		let args = link.split("/", otpauthScheme.length);
 		let type = args[2]; //Returns 'hotp' or 'totp'
 		let issuer = args[3].split(":")[0]?.split("?")[0]; //Returns issuer
 		let client =
@@ -42,9 +61,9 @@ export function getTOTPByLink(link) {
 	}
 }
 
-function getHashType(algorithm) {
-	if (algorithm == "SHA1") return "SHA-1";
-	if (algorithm == "SHA256") return "SHA-256";
-	if (algorithm == "SHA512") return "SHA-512";
-	else return "SHA-1";
-}
+function getByGoogleMigrationScheme(link){
+    console.log("Hello")
+    let data = link.split("data=")[1]; //Returns secret
+    let decodedProto = decodeProto(base64decode(data));
+    console.log(decodedProto)
+}
\ No newline at end of file