diff --git a/src/App.vue b/src/App.vue
index 8e91d240ebaf6814905058248b8469547282e93c..bdaa168d9f7c10dc24ce307ec4b087f510fa2c4b 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -6,18 +6,16 @@ import AppSidebar from '@/components/sidebar';
 import { SidebarProvider } from '@/components/ui/sidebar';
 import ToggleSidebar from './components/sidebar/ToggleSidebar.vue';
 import { Toaster } from 'vue-sonner';
+import { useUserStore } from './stores/user.store';
+import { getWax } from './stores/wax.store';
 
 const WalletOnboarding = defineAsyncComponent(() => import('@/components/onboarding/index'));
 
 const hasUser = ref(true);
 const settingsStore = useSettingsStore();
 const walletStore = useWalletStore();
-onMounted(() => {
-  settingsStore.loadSettings();
-  hasUser.value = settingsStore.settings.account !== undefined;
-  if (hasUser.value)
-    void walletStore.createWalletFor(settingsStore.settings);
-
+const userStore = useUserStore();
+onMounted(async() => {
   if (window.matchMedia) {
     const media = window.matchMedia('(prefers-color-scheme: dark)');
     if (media.matches)
@@ -26,8 +24,17 @@ onMounted(() => {
       document.documentElement.classList[event.matches ? 'add' : 'remove']('dark');
     });
   }
+
+  settingsStore.loadSettings();
+  hasUser.value = settingsStore.settings.account !== undefined;
+  if (hasUser.value) {
+    void walletStore.createWalletFor(settingsStore.settings);
+    const wax = await getWax();
+    const { accounts: [ account ] } = await wax.api.database_api.find_accounts({ accounts: [ settingsStore.settings.account! ], delayed_votes_active: false });
+    void userStore.setUserData(account);
+  }
 });
-const complete = (data: { account: string; wallet: UsedWallet }) => {
+const complete = async(data: { account: string; wallet: UsedWallet }) => {
   hasUser.value = true;
   const settings = {
     account: data.account,
@@ -35,6 +42,9 @@ const complete = (data: { account: string; wallet: UsedWallet }) => {
   };
   settingsStore.setSettings(settings);
   void walletStore.createWalletFor(settings);
+  const wax = await getWax();
+  const { accounts: [ account ] } = await wax.api.database_api.find_accounts({ accounts: [ settingsStore.settings.account! ], delayed_votes_active: false });
+  void userStore.setUserData(account);
 };
 </script>
 
diff --git a/src/components/onboarding/wallets/metamask/MetamaskConnect.vue b/src/components/onboarding/wallets/metamask/MetamaskConnect.vue
index b5c6d374c82897bbbca8273c68c66c5d79f798e5..cc2039bc0bfbd20c43a40324f8ab9deb2c4e0179 100644
--- a/src/components/onboarding/wallets/metamask/MetamaskConnect.vue
+++ b/src/components/onboarding/wallets/metamask/MetamaskConnect.vue
@@ -15,7 +15,7 @@ import { Separator } from '@/components/ui/separator';
 import PublicKey from '@/components/hive/PublicKey.vue';
 import { Checkbox } from '@/components/ui/checkbox'
 import { getWax } from '@/stores/wax.store';
-import { AccountAuthorityUpdateOperation, type TRole } from "@hiveio/wax/vite";
+import type { TRole } from "@hiveio/wax/vite";
 
 const emit = defineEmits(["setaccount", "close"]);
 
@@ -135,6 +135,7 @@ 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])
diff --git a/src/components/sidebar/AppSidebar.vue b/src/components/sidebar/AppSidebar.vue
index 7fb651a1a031bbaedfa7c3d4cbab75c62bd56b8d..4e69153d69ceb384640c6a2856005b65b95dbb99 100644
--- a/src/components/sidebar/AppSidebar.vue
+++ b/src/components/sidebar/AppSidebar.vue
@@ -6,6 +6,7 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
 import { useSettingsStore, getWalletIcon } from '@/stores/settings.store';
 import { computed } from 'vue';
 import { Button } from '@/components/ui/button';
+import { useUserStore } from "@/stores/user.store";
 
 const settingsStore = useSettingsStore();
 const hasUser = computed(() => settingsStore.settings.account !== undefined);
@@ -17,6 +18,8 @@ const logout = () => {
 
 const { toggleSidebar, isMobile } = useSidebar();
 
+const userStore = useUserStore();
+
 const items = [
   {
     title: "Home",
@@ -51,7 +54,7 @@ const items = [
     <SidebarHeader class="pb-0">
       <div class="flex items-center rounded-lg p-2 mt-1 mx-1 bg-background/40 border" v-if="settingsStore.isLoaded && hasUser">
         <Avatar class="w-8 h-8 mr-2">
-          <AvatarImage src="https://github.com/unovue.png" alt="@unovue" />
+          <AvatarImage v-if="userStore.profileImage" :src="userStore.profileImage" />
           <AvatarFallback>{{ settingsStore.settings.account?.slice(0, 2) }}</AvatarFallback>
         </Avatar>
         <span class="font-bold">@{{ settingsStore.settings.account }}</span>
diff --git a/src/components/ui/button/Button.vue b/src/components/ui/button/Button.vue
index 17dc84d72766a934ce4a01d560a6ab10898bd55b..3ba549bf4422162af85c42cf4750617820cea54d 100644
--- a/src/components/ui/button/Button.vue
+++ b/src/components/ui/button/Button.vue
@@ -3,15 +3,19 @@ import type { HTMLAttributes } from 'vue'
 import { cn } from '@/lib/utils'
 import { Primitive, type PrimitiveProps } from 'reka-ui'
 import { type ButtonVariants, buttonVariants } from '.'
+import { mdiLoading } from '@mdi/js'
 
 interface Props extends PrimitiveProps {
   variant?: ButtonVariants['variant']
   size?: ButtonVariants['size']
   class?: HTMLAttributes['class']
+  loading?: boolean
+  disabled?: boolean
 }
 
 const props = withDefaults(defineProps<Props>(), {
   as: 'button',
+  loading: false
 })
 </script>
 
@@ -19,8 +23,16 @@ const props = withDefaults(defineProps<Props>(), {
   <Primitive
     :as="as"
     :as-child="asChild"
-    :class="cn(buttonVariants({ variant, size }), props.class)"
+    :disabled="loading || disabled"
+    :class="[ cn(buttonVariants({ variant, size }), props.class)]"
   >
-    <slot />
+    <span v-if="loading" class="animate-spin absolute mx-auto">
+      <svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path :style="{
+        fill: !variant || variant === 'default' ? 'hsl(var(--background))' : 'hsl(var(--foreground))'
+      }" :d="mdiLoading"/></svg>
+    </span>
+    <span :style="{ 'visibility': loading ? 'hidden' : 'visible' }" class="inline-flex items-center justify-center gap-2">
+      <slot/>
+    </span>
   </Primitive>
 </template>
diff --git a/src/components/utilcards/AuthorityCard.vue b/src/components/utilcards/AuthorityCard.vue
index c7d6f1bbe27f902d938fb9a25d235c3b2e59b599..d387af110004fc971a9d66151fa45dc2dfaf5d64 100644
--- a/src/components/utilcards/AuthorityCard.vue
+++ b/src/components/utilcards/AuthorityCard.vue
@@ -4,7 +4,7 @@ import { Skeleton } from '@/components/ui/skeleton';
 import { mdiAccountKeyOutline } from '@mdi/js';
 import { useSettingsStore } from '@/stores/settings.store';
 import { computed, onMounted, ref, watch } from 'vue';
-import { AccountAuthorityUpdateOperation, type authority } from '@hiveio/wax/vite';
+import type { authority } from '@hiveio/wax/vite';
 import { getWax } from '@/stores/wax.store';
 import PublicKey from '@/components/hive/PublicKey.vue';
 
@@ -20,6 +20,7 @@ const retrieveAuthority = async() => {
   try {
     const wax = await getWax();
 
+    const { AccountAuthorityUpdateOperation } = await import("@hiveio/wax/vite");
     const op = await AccountAuthorityUpdateOperation.createFor(wax, settingsStore.settings.account!);
     memoKey.value = op.role("memo").value;
     postingAuthority.value = op.role("posting").value;
diff --git a/src/components/utilcards/ConfirmAccountUpdateCard.vue b/src/components/utilcards/ConfirmAccountUpdateCard.vue
index 9eb95739bf2bbb004e1fe95671f670eb7ab39cf2..22b9094f1495561f7fe75faa5af457080317202a 100644
--- a/src/components/utilcards/ConfirmAccountUpdateCard.vue
+++ b/src/components/utilcards/ConfirmAccountUpdateCard.vue
@@ -9,8 +9,7 @@ import { onMounted, ref } from 'vue';
 import { useRouter } from 'vue-router';
 import { getWax } from '@/stores/wax.store';
 import { useWalletStore } from '@/stores/wallet.store';
-import { AccountAuthorityUpdateOperation } from '@hiveio/wax';
-import { toastError } from '@/lib/parse-error';
+import { toastError } from '@/utils/parse-error';
 
 const settings = useSettingsStore();
 
@@ -43,6 +42,7 @@ const updateAuthority = async() => {
 
     const wax = await getWax();
     const tx = await wax.createTransaction();
+    const { AccountAuthorityUpdateOperation } = await import("@hiveio/wax/vite");
     const op = await AccountAuthorityUpdateOperation.createFor(wax, creator.value.startsWith('@') ? creator.value.slice(1) : creator.value);
     if (memoKey.value)
       op.role("memo").set(memoKey.value);
@@ -95,7 +95,7 @@ const updateAuthority = async() => {
           <Label for="updateAuthority_ownerKey">Add Owner Key</Label>
           <Input id="updateAuthority_ownerKey" placeholder="Nothing to add" v-model="ownerKey" class="my-2" />
         </div>
-        <Button class="my-2" @click="updateAuthority" :disabled="isLoading">Update Authority</Button>
+        <Button class="my-2" @click="updateAuthority" :loading="isLoading">Update Authority</Button>
         <p>Note: By clicking the above button, the transaction will be created, signed, and broadcasted immediately to the mainnet chain</p>
       </div>
     </CardContent>
diff --git a/src/components/utilcards/ConfirmCreateAccountCard.vue b/src/components/utilcards/ConfirmCreateAccountCard.vue
index ba0859f2daffc26c4cfdf212b7345705529f93c7..947bcdda42df3067461fee477cb01aab5df319b7 100644
--- a/src/components/utilcards/ConfirmCreateAccountCard.vue
+++ b/src/components/utilcards/ConfirmCreateAccountCard.vue
@@ -12,7 +12,7 @@ import { onMounted, ref } from 'vue';
 import { useRouter } from 'vue-router';
 import { getWax } from '@/stores/wax.store';
 import { useWalletStore } from '@/stores/wallet.store';
-import { toastError } from '@/lib/parse-error';
+import { toastError } from '@/utils/parse-error';
 
 const settings = useSettingsStore();
 
@@ -178,7 +178,7 @@ const createAccount = async() => {
             <Label for="createAccount_r3">Create claimed</Label>
           </div>
         </RadioGroup>
-        <Button @click="createAccount" :disabled="isLoading">Create account</Button>
+        <Button @click="createAccount" :loading="isLoading">Create account</Button>
         <p>Note: By clicking the above button, the transaction will be created, signed, and broadcasted immediately to the mainnet chain</p>
       </div>
     </CardContent>
diff --git a/src/components/utilcards/MemoEncryptCard.vue b/src/components/utilcards/MemoEncryptCard.vue
index 5e7912de528f93fea053e3b17a5171f88b4652f2..c429ee39c792c1d0218d766d2a7caa40edb005c0 100644
--- a/src/components/utilcards/MemoEncryptCard.vue
+++ b/src/components/utilcards/MemoEncryptCard.vue
@@ -9,7 +9,7 @@ import { Switch } from '@/components/ui/switch';
 import { useWalletStore } from '@/stores/wallet.store';
 import { getWax } from '@/stores/wax.store';
 import { useSettingsStore } from '@/stores/settings.store';
-import { toastError } from '@/lib/parse-error';
+import { toastError } from '@/utils/parse-error';
 
 const walletStore = useWalletStore();
 const settingsStore = useSettingsStore();
@@ -18,6 +18,7 @@ const hasWallet = computed(() => walletStore.hasWallet);
 const wallet = computed(() => walletStore.wallet);
 
 const isEncrypt = ref(false);
+const isLoading = ref(false);
 const encryptForKey = ref('');
 const inputData = ref('');
 const outputData = ref('');
@@ -37,13 +38,21 @@ const getMemoKeyForUser = async(user: string): Promise<string | void> => {
 }
 
 const useMyMemoKey = async () => {
-  const key = await getMemoKeyForUser(settingsStore.account!);
-  if (key)
-    encryptForKey.value = key;
+  try {
+    isLoading.value = true;
+
+    const key = await getMemoKeyForUser(settingsStore.account!);
+    if (key)
+      encryptForKey.value = key;
+  } finally {
+    isLoading.value = false;
+  }
 }
 
 const encryptOrDecrypt = async () => {
   try {
+    isLoading.value = true;
+
     if (isEncrypt.value) {
       let publicKey: string;
       let accountOrKey = encryptForKey.value;
@@ -60,6 +69,8 @@ const encryptOrDecrypt = async () => {
     }
   } catch (error) {
     toastError(`Error ${isEncrypt.value ? 'encrypting' : 'decrypting'} memo`, error);
+  } finally {
+    isLoading.value = false;
   }
 };
 </script>
@@ -84,7 +95,7 @@ const encryptOrDecrypt = async () => {
       <div class="flex mb-4 underline text-sm" v-if="isEncrypt">
         <a @click="useMyMemoKey" class="ml-auto mr-1 cursor-pointer" style="color: hsla(var(--foreground) / 70%)">Use my memo key</a>
       </div>
-      <Button :disabled="!hasWallet || (!encryptForKey && isEncrypt)" @click="encryptOrDecrypt">{{ isEncrypt ? "Encrypt" : "Decrypt" }}</Button>
+      <Button :loading="isLoading" :disabled="!hasWallet || (!encryptForKey && isEncrypt)" @click="encryptOrDecrypt">{{ isEncrypt ? "Encrypt" : "Decrypt" }}</Button>
       <Textarea v-model="outputData" placeholder="Output" copy-enabled class="my-4" disabled/>
     </CardContent>
   </Card>
diff --git a/src/components/utilcards/SignTransactionCard.vue b/src/components/utilcards/SignTransactionCard.vue
index d96fa68c9f5401af3bf249c33cc4a30d3d7f65a7..fe94e7554f3b635d8275203f18aa071b59561055 100644
--- a/src/components/utilcards/SignTransactionCard.vue
+++ b/src/components/utilcards/SignTransactionCard.vue
@@ -8,7 +8,7 @@ import { useWalletStore } from '@/stores/wallet.store';
 import { getWax } from '@/stores/wax.store';
 import type { ITransactionBase, TRole } from '@hiveio/wax/vite';
 import { useRouter } from 'vue-router';
-import { toastError } from '@/lib/parse-error';
+import { toastError } from '@/utils/parse-error';
 
 const walletStore = useWalletStore();
 
@@ -21,6 +21,7 @@ const outputData = ref('');
 const router = useRouter();
 
 const isLoading = ref(false);
+const isBroadcasting = ref(false);
 
 const sign = async () => {
   try {
@@ -63,7 +64,7 @@ const sign = async () => {
 
 const broadcast = async () => {
   try {
-    isLoading.value = true;
+    isBroadcasting.value = true;
 
     const wax = await getWax();
 
@@ -74,7 +75,7 @@ const broadcast = async () => {
   } catch (error) {
     toastError('Error broadcasting transaction', error);
   } finally {
-    isLoading.value = false;
+    isBroadcasting.value = false;
   }
 };
 
@@ -95,11 +96,11 @@ onMounted(() => {
     <CardContent>
       <Textarea v-model="inputData" placeholder="Transaction in API JSON form" class="my-4"/>
       <div class="my-4 space-x-4">
-        <Button :disabled="!inputData || !hasWallet || isLoading" @click="sign">Sign transaction</Button>
+        <Button :disabled="!inputData || !hasWallet || isBroadcasting" :loading="isLoading" @click="sign">Sign transaction</Button>
       </div>
       <Textarea v-model="outputData" placeholder="Signature" copy-enabled class="my-4" disabled/>
       <div class="my-4 space-x-4">
-        <Button :disabled="!outputData || isLoading" @click="broadcast">Broadcast signed transaction</Button>
+        <Button :disabled="!outputData || isLoading" :loading="isBroadcasting" @click="broadcast">Broadcast signed transaction</Button>
       </div>
     </CardContent>
   </Card>
diff --git a/src/lib/parse-error.ts b/src/lib/parse-error.ts
deleted file mode 100644
index dd277c7e5555ecbeed80d1531244a355b9313c22..0000000000000000000000000000000000000000
--- a/src/lib/parse-error.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { WaxChainApiError, WaxError } from "@hiveio/wax/vite";
-import { toast } from "vue-sonner";
-
-export const toastError = (title: string, error: unknown) => {
-  let description: string;
-
-  if (typeof error === "object" && error) {
-    if (error instanceof WaxError) {
-      if (error instanceof WaxChainApiError) {
-        if (error.apiError
-            && typeof error.apiError === "object"
-            && "error" in error.apiError
-            && typeof error.apiError.error === "object"
-            && error.apiError.error
-            && "message" in error.apiError.error
-            && typeof error.apiError.error.message === "string")
-          description = error.apiError.error.message;
-        else
-          description = error.message;
-      } else {
-        description = error.message;
-      }
-    } else if ("message" in error) {
-      description = (error as Error).message;
-    } else {
-      description = String(error);
-    }
-  } else {
-    description = String(error);
-  }
-
-  toast.error(title, { description });
-};
diff --git a/src/stores/user.store.ts b/src/stores/user.store.ts
new file mode 100644
index 0000000000000000000000000000000000000000..306afb2abd474c0712b644f6bad6a4a59e43fb7c
--- /dev/null
+++ b/src/stores/user.store.ts
@@ -0,0 +1,29 @@
+import { defineStore } from "pinia"
+import type { ApiAccount } from "@hiveio/wax/vite";
+
+export const useUserStore = defineStore('user', {
+  state: () => ({
+    isReady: false,
+    parsedJsonMetadata: undefined as undefined | Record<string, any>,
+    userData: undefined as undefined | ApiAccount
+  }),
+  getters: {
+    profileImage: (ctx): undefined | string => ctx.isReady ? ctx.parsedJsonMetadata?.profile?.profile_image : undefined,
+    name: (ctx): undefined | string => ctx.isReady ? ctx.parsedJsonMetadata?.profile?.name : undefined,
+    about: (ctx): undefined | string => ctx.isReady ? ctx.parsedJsonMetadata?.profile?.about : undefined,
+    website: (ctx): undefined | string => ctx.isReady ? ctx.parsedJsonMetadata?.profile?.website : undefined
+  },
+  actions: {
+    // Used for logout
+    resetSettings() {
+      this.isReady = false;
+      this.parsedJsonMetadata = undefined;
+      this.userData = undefined;
+    },
+    setUserData(data: ApiAccount) {
+      this.userData = data;
+      this.parsedJsonMetadata = JSON.parse(data.posting_json_metadata);
+      this.isReady = true;
+    }
+  }
+})
diff --git a/src/stores/wax.store.ts b/src/stores/wax.store.ts
index 0ebd22bffe087242ad9ccd68326a5b66c1bf606f..ff6d9f53687de480656406d8ce1cefd64d21958e 100644
--- a/src/stores/wax.store.ts
+++ b/src/stores/wax.store.ts
@@ -1,4 +1,4 @@
-import { createHiveChain, type TWaxExtended, type asset } from "@hiveio/wax/vite";
+import type { TWaxExtended, asset } from "@hiveio/wax/vite";
 
 export interface WaxApi {
   database_api: {
@@ -17,7 +17,7 @@ let chain: TWaxExtended<WaxApi>;
 
 export const getWax = async() => {
   if (!chain)
-    chain = (await createHiveChain()).extend<WaxApi>();
+    chain = (await (await import("@hiveio/wax/vite")).createHiveChain()).extend<WaxApi>();
 
   return chain;
 };
diff --git a/src/utils/parse-error.ts b/src/utils/parse-error.ts
new file mode 100644
index 0000000000000000000000000000000000000000..18b2ef13a1f6239ba5d373d1a29f1c2d5fdf0522
--- /dev/null
+++ b/src/utils/parse-error.ts
@@ -0,0 +1,24 @@
+import { toast } from "vue-sonner";
+
+export const toastError = (title: string, error: unknown) => {
+  let description: string;
+
+  if (typeof error === "object" && error && "message" in error) {
+    if ("name" in error
+        && error.name === "WaxChainApiError"
+        && "apiError" in error
+        && error.apiError
+        && typeof error.apiError === "object"
+        && "error" in error.apiError
+        && typeof error.apiError.error === "object"
+        && error.apiError.error
+        && "message" in error.apiError.error
+        && typeof error.apiError.error.message === "string")
+      description = error.apiError.error.message as string;
+    else
+      description = error.message as string;
+  } else
+    description = String(error);
+
+  toast.error(title, { description });
+};