diff --git a/public/bg.svg b/public/bg.svg
deleted file mode 100644
index 5f756111bcb575f0931f1d96cebdbb55a74480b8..0000000000000000000000000000000000000000
--- a/public/bg.svg
+++ /dev/null
@@ -1,71 +0,0 @@
-<svg viewBox="0 0 1900 1000" xmlns="http://www.w3.org/2000/svg" fill="none" style="
-  opacity:0.3;
-  --bg-base: rgb(20, 20, 20);
-  --accent-1:rgba(255, 90, 109, 0.56);
-  --accent-2:rgb(118, 56, 81);
-  --accent-3:rgb(198, 112, 78);
-  --accent-4:rgb(116, 0, 73);
-  --accent-5:rgb(112, 54, 47);
-  --accent-6:rgba(253, 39, 39, 0.32);
-  --accent-7:rgb(111, 37, 116);
-  ">
- <defs>
-  <radialGradient gradientTransform="matrix(-381.8856201171875,-718.64599609375,1352.26904296875,-718.5903930664062,1460.033935546875,1616.3768310546875)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint3_radial">
-   <stop stop-color="var(--bg-base)"/>
-   <stop stop-color="var(--bg-base)" offset="0.82292"/>
-   <stop stop-opacity="0" stop-color="var(--bg-base)" offset="1"/>
-  </radialGradient>
-  <radialGradient gradientTransform="matrix(-381.8856201171875,-718.64599609375,1352.26904296875,-718.5903930664062,1523.080078125,1511.2974853515625)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint4_radial">
-   <stop stop-color="var(--bg-base)"/>
-   <stop stop-color="var(--bg-base)" offset="0.82292"/>
-   <stop stop-opacity="0" stop-color="var(--bg-base)" offset="1"/>
-  </radialGradient>
-  <radialGradient gradientTransform="matrix(-367.9964599609375,668.3052368164062,-775.7698364257812,-427.1709289550781,1491.2763671875,646.0341186523438)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint5_radial">
-   <stop stop-color="var(--accent-1)" offset="0.32813"/>
-   <stop stop-opacity="0" stop-color="white" offset="1"/>
-  </radialGradient>
-  <radialGradient gradientTransform="matrix(-708.8882446289062,428.3532409667969,-802.1248168945312,-1340.3924560546875,1895.1649169921875,806.4420166015625)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint6_radial">
-   <stop stop-color="var(--bg-base)"/>
-   <stop stop-color="var(--bg-base)" offset="0.78938"/>
-   <stop stop-opacity="0" stop-color="var(--bg-base)" offset="1"/>
-  </radialGradient>
-  <radialGradient gradientTransform="matrix(1168.929931640625,2499.95166015625,-2448.661865234375,1144.9478759765625,-137.4949951171875,-345.2243957519531)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint0_radial">
-   <stop stop-color="var(--bg-base)"/>
-   <stop stop-color="var(--accent-1)" offset="0.08333"/>
-   <stop stop-color="var(--accent-2)" offset="0.36458"/>
-   <stop stop-color="var(--bg-base)" offset="0.65804"/>
-   <stop stop-color="var(--accent-3)" offset="0.79852"/>
-   <stop stop-color="var(--bg-base)" offset="0.94271"/>
-   <stop stop-color="var(--bg-base)" offset="1"/>
-  </radialGradient>
-  <radialGradient gradientTransform="matrix(1168.929931640625,2499.95166015625,-2448.661865234375,1144.9478759765625,293.6920166015625,64.984619140625)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint1_radial">
-   <stop stop-color="var(--bg-base)"/>
-   <stop stop-color="var(--accent-4)" offset="0.08333"/>
-   <stop stop-color="var(--accent-5)" offset="0.3338"/>
-   <stop stop-color="var(--bg-base)" offset="0.65804"/>
-   <stop stop-color="var(--accent-3)" offset="0.79852"/>
-   <stop stop-color="var(--bg-base)" offset="0.94271"/>
-   <stop stop-color="var(--bg-base)" offset="1"/>
-  </radialGradient>
-  <radialGradient gradientTransform="matrix(1168.929931640625,2499.95166015625,-2448.661865234375,1144.9478759765625,598.625732421875,180.31497192382812)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint2_radial">
-   <stop stop-color="var(--bg-base)"/>
-   <stop stop-opacity="0" stop-color="var(--accent-6)" offset="0.14063"/>
-   <stop stop-color="var(--accent-7)" offset="0.3338"/>
-   <stop stop-color="var(--bg-base)" offset="0.65804"/>
-   <stop stop-color="var(--accent-3)" offset="0.79852"/>
-   <stop stop-color="var(--bg-base)" offset="0.94271"/>
-   <stop stop-color="var(--bg-base)" offset="1"/>
-  </radialGradient>
- </defs>
- <g>
-  <g id="svg_1">
-   <path id="svg_2" fill="url(#paint0_radial)" d="m1502.44912,585.67754c33.10025,39.73622 61.75559,56.73205 38.47076,89.01439c-207.12817,287.18063 -533.50156,932.74603 -749.82619,1033.23391c-875.97368,290.34215 -1794.58437,-383.1195 -929.17869,-874.49315c865.40612,-491.37708 -320.65596,-399.01561 171.18459,-730.25605c572.8894,-385.82665 1337.65958,210.53419 1469.34952,482.5009z"/>
-   <path id="svg_3" fill="url(#paint1_radial)" d="m587.07817,485.4941l419.66703,159.06733c24.18089,9.16687 41.4162,25.71878 46.94265,45.09221l69.01414,241.88691l313.39974,-96.93921c25.09839,-7.76404 53.68243,-6.95072 77.8676,2.21572l419.66703,159.06737c44.52885,16.87946 61.75559,56.73076 38.47076,89.01482l-111.72942,154.90774c-9.73238,13.49242 -25.6043,24.12944 -44.92329,30.10606l-547.85575,169.45915l120.53144,422.44097c4.32598,15.15593 1.1576,30.93353 -8.9435,44.57172l-156.90567,211.74998l-496.69002,-188.26365c-24.18518,-9.16644 -41.4162,-25.71577 -46.94265,-45.0905c-121.18569,-424.72615 -163.28659,-464.9033 -346.7638,-1107.95457c-17.09383,-59.91029 10.94014,-95.04032 20.67252,-108.5336l111.72985,-154.90851c23.28397,-32.28243 78.25947,-44.76903 122.79132,-27.88995z"/>
-   <path id="svg_4" fill="url(#paint2_radial)" d="m892.01032,600.82489l419.66703,159.06737c24.18518,9.16644 41.4162,25.71835 46.94265,45.09178l69.01843,241.88605l313.39546,-96.93792c25.10268,-7.76447 53.68672,-6.95072 77.8676,2.21572l419.66703,159.06737c44.53314,16.87946 61.75559,56.73076 38.47076,89.01482l-111.72942,154.90774c-9.73238,13.49242 -25.6043,24.12944 -44.92329,30.10606l-547.85146,169.45915l120.53144,422.44097c4.32169,15.15593 1.1576,30.93353 -8.94779,44.57172l-156.90567,211.74998l-496.69002,-188.26365c-24.18518,-9.16644 -41.4162,-25.71577 -46.94265,-45.0905l-69.01414,-241.88605l-313.40017,96.93792c-25.10096,7.76447 -53.68414,6.94986 -77.86803,-2.21658c0,0 -435.59683,-164.42146 -346.34633,-402.50031c89.25033,-238.07456 341.27735,-122.28069 592.71786,-200.05397l-120.6472,-422.84656c-4.25738,-14.91069 -1.26478,-30.42933 8.4676,-43.92261l111.72942,-154.9086c23.28482,-32.28234 78.26204,-44.76894 122.79089,-27.88991z"/>
-   <path id="svg_5" fill="url(#paint3_radial)" d="m484.48046,2237.81313l-319.39785,-1215.0982l2173.29209,-725.58785l1371.32646,1940.68605l-3225.2207,0z"/>
-   <path id="svg_6" fill="url(#paint4_radial)" d="m547.5287,2132.73345l-319.39798,-1215.0982l2173.29007,-725.58785l1371.32646,1940.68605l-3225.21855,0z"/>
-   <ellipse id="svg_7" fill="url(#paint5_radial)" ry="668.30572" rx="728.49213" cy="646.03415" cx="1234.93732"/>
-   <path id="svg_8" fill="url(#paint6_radial)" d="m2824.13444,684.91842l-1735.35896,1585.86861l-837.3177,-2104.40458l1818.07193,-1439.64029l754.60472,1958.17626z" opacity="0.5"/>
-  </g>
- </g>
-</svg>
\ No newline at end of file
diff --git a/src/components/onboarding/wallets/keychain/KeychainConnect.vue b/src/components/onboarding/wallets/keychain/KeychainConnect.vue
index 1abdcdb48bb1ad2f2ad8cbe62e341ecd529b251e..751e19133122db5d5a579c84b871496f5bb53d9e 100644
--- a/src/components/onboarding/wallets/keychain/KeychainConnect.vue
+++ b/src/components/onboarding/wallets/keychain/KeychainConnect.vue
@@ -6,6 +6,7 @@ import { ref } from 'vue';
 import { mdiClose } from '@mdi/js';
 import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
 import { UsedWallet, getWalletIcon } from '@/stores/settings.store';
+import { toastError } from "@/utils/parse-error";
 
 const emit = defineEmits(["setaccount", "close"]);
 
@@ -14,13 +15,11 @@ const close = () => {
 };
 
 const isLoading = ref(false);
-const errorMsg = ref<string | null>(null);
 const selectedLevel = ref<string | null>('posting');
 
 const connect = async() => {
   try {
     isLoading.value = true;
-    errorMsg.value = null;
 
     const response = await new Promise((resolve, reject) => {
       (window as any).hive_keychain.requestSignBuffer(
@@ -40,10 +39,7 @@ const connect = async() => {
 
     emit("setaccount", response.data.username);
   } catch (error) {
-    if (typeof error === "object" && error && "message" in error)
-      errorMsg.value = error.message as string;
-    else
-      errorMsg.value = String(error);
+    toastError('Failed to connect to Keychain', error);
   } finally {
     isLoading.value = false;
   }
@@ -97,7 +93,6 @@ const connect = async() => {
       </div>
     </CardContent>
     <CardFooter>
-      <span class="text-red-400" v-if="errorMsg"><span class="font-bold">Error: </span>{{ errorMsg }}</span>
     </CardFooter>
   </Card>
 </template>
diff --git a/src/components/onboarding/wallets/metamask/MetamaskConnect.vue b/src/components/onboarding/wallets/metamask/MetamaskConnect.vue
index 649db7e14faf02ebc1d40eee2febdcbc2ce0f60f..b71a366ba719edcd1f9be8744bc22ed1ffbe2f93 100644
--- a/src/components/onboarding/wallets/metamask/MetamaskConnect.vue
+++ b/src/components/onboarding/wallets/metamask/MetamaskConnect.vue
@@ -12,6 +12,7 @@ import { useMetamaskStore } from "@/stores/metamask.store";
 import { Combobox, ComboboxAnchor, ComboboxTrigger, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from '@/components/ui/combobox';
 import { Check, Search } from 'lucide-vue-next';
 import { Separator } from '@/components/ui/separator';
+import { toastError } from "@/utils/parse-error";
 import PublicKey from '@/components/hive/PublicKey.vue';
 import { Checkbox } from '@/components/ui/checkbox'
 import { getWax } from '@/stores/wax.store';
@@ -38,7 +39,6 @@ const close = () => {
 const metamaskStore = useMetamaskStore();
 
 const isLoading = ref(false);
-const errorMsg = ref<string | null>(null);
 const accountName = ref<string | null>(null);
 const createAccountNameOperation = ref<string | null>(null);
 const updateAccountNameOperation = ref<string | null>(null);
@@ -49,7 +49,6 @@ const isMetamaskSnapInstalled = ref<boolean>(false);
 
 const applyPublicKeys = async () => {
   isLoading.value = true;
-  errorMsg.value = null;
   try {
     const { publicKeys } = await metamaskStore.call("hive_getPublicKeys", {
       keys: [{
@@ -73,10 +72,7 @@ const applyPublicKeys = async () => {
 
     accountsMatchingKeys.value = [...new Set(response.accounts.flatMap((node: string[]) => node))] as string[];
   } catch (error) {
-    if (typeof error === "object" && error && "message" in error)
-      errorMsg.value = error.message as string;
-    else
-      errorMsg.value = String(error);
+    toastError("Failed to match Metamask public keys", error);
   } finally {
     isLoading.value = false;
   }
@@ -85,20 +81,23 @@ const applyPublicKeys = async () => {
 const accountNameValid = ref(false);
 
 const validateAccountName = async() => {
-  if(!createAccountNameOperation.value)
-    return accountNameValid.value = false;
+  try {
+    if(!createAccountNameOperation.value)
+      return accountNameValid.value = false;
 
-  const accountName = createAccountNameOperation.value.startsWith("@") ? createAccountNameOperation.value.slice(1) : createAccountNameOperation.value;
-  if (!accountName)
-    return accountNameValid.value = false;
+    const accountName = createAccountNameOperation.value.startsWith("@") ? createAccountNameOperation.value.slice(1) : createAccountNameOperation.value;
+    if (!accountName)
+      return accountNameValid.value = false;
 
-  const wax = await getWax();
-  return accountNameValid.value = wax.isValidAccountName(accountName);
+    const wax = await getWax();
+    return accountNameValid.value = wax.isValidAccountName(accountName);
+  } catch (error) {
+    toastError("Failed to validate account name", error);
+  }
 }
 
 const connect = async (showError = true) => {
   isLoading.value = true;
-  errorMsg.value = null;
   try {
     await metamaskStore.connect();
 
@@ -110,10 +109,7 @@ const connect = async (showError = true) => {
     if (!showError)
       return;
 
-    if (typeof error === "object" && error && "message" in error)
-      errorMsg.value = error.message as string;
-    else
-      errorMsg.value = String(error);
+    toastError("Failed to connect to Metamask", error);
   } finally {
     isLoading.value = false;
   };
@@ -121,7 +117,6 @@ const connect = async (showError = true) => {
 
 const install = async () => {
   isLoading.value = true;
-  errorMsg.value = null;
   try {
     await metamaskStore.install();
     isMetamaskSnapInstalled.value = metamaskStore.isInstalled!;
@@ -129,10 +124,7 @@ const install = async () => {
     if (isMetamaskSnapInstalled.value)
       void applyPublicKeys();
   } catch (error) {
-    if (typeof error === "object" && error && "message" in error)
-      errorMsg.value = error.message as string;
-    else
-      errorMsg.value = String(error);
+    toastError("Failed to install Metamask Snap", error);
   } finally {
     isLoading.value = false;
   };
@@ -142,21 +134,25 @@ onMounted(() => {
   void connect(false);
 });
 
-const generateAccountUpdateTransaction = async(): Promise<string> => {
-  const wax = await getWax();
-  const tx = await wax.createTransaction();
-  const accountName = updateAccountNameOperation.value!.startsWith('@') ? updateAccountNameOperation.value!.slice(1) : updateAccountNameOperation.value!;
-  const { AccountAuthorityUpdateOperation } = await import("@hiveio/wax/vite");
-  const op = await AccountAuthorityUpdateOperation.createFor(wax, accountName);
-  for(const key in updateAuthType) {
-    if (updateAuthType[key as TRole])
-      if (key === "memo")
-        op.role("memo").set(metamaskPublicKeys.value!.find(node => node.role === key)!.publicKey);
-      else
-        op.role(key as Exclude<TRole, "memo">).add(metamaskPublicKeys.value!.find(node => node.role === key)!.publicKey);
-    }
-  tx.pushOperation(op);
-  return tx.toApi();
+const generateAccountUpdateTransaction = async(): Promise<string | void> => {
+  try {
+    const wax = await getWax();
+    const tx = await wax.createTransaction();
+    const accountName = updateAccountNameOperation.value!.startsWith('@') ? updateAccountNameOperation.value!.slice(1) : updateAccountNameOperation.value!;
+    const { AccountAuthorityUpdateOperation } = await import("@hiveio/wax/vite");
+    const op = await AccountAuthorityUpdateOperation.createFor(wax, accountName);
+    for(const key in updateAuthType) {
+      if (updateAuthType[key as TRole])
+        if (key === "memo")
+          op.role("memo").set(metamaskPublicKeys.value!.find(node => node.role === key)!.publicKey);
+        else
+          op.role(key as Exclude<TRole, "memo">).add(metamaskPublicKeys.value!.find(node => node.role === key)!.publicKey);
+      }
+    tx.pushOperation(op);
+    return tx.toApi();
+  } catch (error) {
+    toastError("Failed to generate account update transaction", error);
+  }
 };
 const getAccountCreateSigningLink = (): string => {
   const accountName = createAccountNameOperation.value!.startsWith('@') ? createAccountNameOperation.value!.slice(1) : createAccountNameOperation.value!;
@@ -358,7 +354,6 @@ const updateAccountName = (value: string | any) => {
       </div>
     </CardContent>
     <CardFooter>
-      <span class="text-red-400" v-if="errorMsg"><span class="font-bold">Error: </span>{{ errorMsg }}</span>
     </CardFooter>
   </Card>
 </template>
diff --git a/src/components/onboarding/wallets/peakvault/PeakVaultConnect.vue b/src/components/onboarding/wallets/peakvault/PeakVaultConnect.vue
index 27bfa11325c22e4fcd26a15fc5b6ee813d8bafcf..5893c2f381ca06872bf9f37414740ab5959e6f64 100644
--- a/src/components/onboarding/wallets/peakvault/PeakVaultConnect.vue
+++ b/src/components/onboarding/wallets/peakvault/PeakVaultConnect.vue
@@ -5,6 +5,7 @@ import step1 from "@/assets/icons/wallets/peakvault/step1.webp";
 import { ref } from 'vue';
 import { mdiClose } from '@mdi/js';
 import { UsedWallet, getWalletIcon } from '@/stores/settings.store';
+import { toastError } from "@/utils/parse-error";
 
 const emit = defineEmits(["setaccount", "close"]);
 
@@ -13,20 +14,15 @@ const close = () => {
 };
 
 const isLoading = ref(false);
-const errorMsg = ref<string | null>(null);
 const connect = async() => {
   try {
     isLoading.value = true;
-    errorMsg.value = null;
 
     const { result } = await (window as any).peakvault.requestContact();
 
     emit("setaccount", result as string);
   } catch (error) {
-    if (typeof error === "object" && error && "message" in error)
-      errorMsg.value = error.message as string;
-    else
-      errorMsg.value = String(error);
+    toastError('Failed to connect to PeakVault', error);
   } finally {
     isLoading.value = false;
   }
@@ -66,7 +62,6 @@ const connect = async() => {
       </div>
     </CardContent>
     <CardFooter>
-      <span class="text-red-400" v-if="errorMsg"><span class="font-bold">Error: </span>{{ errorMsg }}</span>
     </CardFooter>
   </Card>
 </template>
diff --git a/src/components/ui/button/Button.vue b/src/components/ui/button/Button.vue
index ba01e17dceb546df0d75194e598e4e3f5fc8db23..7514b91ae4f57be8d38683e5c3b8eed184b8dc1a 100644
--- a/src/components/ui/button/Button.vue
+++ b/src/components/ui/button/Button.vue
@@ -12,7 +12,7 @@ interface Props extends PrimitiveProps {
   class?: HTMLAttributes['class']
   loading?: boolean
   disabled?: boolean
-  copy?: string | (() => (string | Promise<string>))
+  copy?: string | (() => (string | void | Promise<string | void>))
 }
 
 const props = withDefaults(defineProps<Props>(), {
@@ -25,13 +25,19 @@ const copyLoading = ref(false);
 const copyBtn = () => {
   if (!props.copy) return;
   const text = typeof props.copy === 'function' ? props.copy() : props.copy;
+  let copied = false;
+
   if(text instanceof Promise)
     text.then((text) => {
-      copyText(text);
+      if (copied = !!text)
+        copyText(text);
     });
-  else
+  else if (copied = !!text)
     copyText(text);
 
+  if (!copied)
+    return;
+
   copyLoading.value = true;
   setTimeout(() => {
     copyLoading.value = false;