diff --git a/src/components/onboarding/wallets/metamask/MetamaskConnect.vue b/src/components/onboarding/wallets/metamask/MetamaskConnect.vue index ac778789316553148abcf3314c6f659ad939c3e8..649db7e14faf02ebc1d40eee2febdcbc2ce0f60f 100644 --- a/src/components/onboarding/wallets/metamask/MetamaskConnect.vue +++ b/src/components/onboarding/wallets/metamask/MetamaskConnect.vue @@ -23,7 +23,7 @@ const showUpdateAccountModal = ref(false); const showCreateAccountModal = ref(false); const updateAuthType: Record<TRole, boolean> = { - owner: true, + owner: false, active: true, posting: true, memo: true @@ -239,7 +239,7 @@ const updateAccountName = (value: string | any) => { </div> <div v-for="key in metamaskPublicKeys" :key="key.publicKey"> <div class="flex items-center p-1"> - <Checkbox :id="`metamask_updateAuth_key-${key.role}`" :defaultValue="true" @update:modelValue="value => { updateAuthType[key.role as TRole] = value as boolean }" /> + <Checkbox :id="`metamask_updateAuth_key-${key.role}`" :defaultValue="updateAuthType[key.role as TRole]" @update:modelValue="value => { updateAuthType[key.role as TRole] = value as boolean }" /> <label :for="`metamask_updateAuth_key-${key.role}`" class="pl-2 w-full flex items-center"> <span class="font-bold">{{ key.role[0].toUpperCase() }}{{ key.role.slice(1) }}</span> <div class="mx-2 border flex-grow border-[hsl(var(--foreground))] opacity-[0.1]" /> @@ -248,7 +248,7 @@ const updateAccountName = (value: string | any) => { </div> </div> <div class="flex items-center flex-col"> - <Button :disabled="isLoading" :copy="getAuthorityUpdateSigningLink" variant="outline" size="lg" class="mt-4 px-8 py-4 border-[#FF5C16] border-[1px]"> + <Button :disabled="isLoading || !updateAccountNameOperation" :copy="getAuthorityUpdateSigningLink" variant="outline" size="lg" class="mt-4 px-8 py-4 border-[#FF5C16] border-[1px]"> <span class="text-md font-bold">Copy signing link</span> </Button> <Separator label="Or" class="mt-8" /> @@ -274,7 +274,7 @@ const updateAccountName = (value: string | any) => { </div> </div> <div class="flex items-center flex-col"> - <Button :copy="getAccountCreateSigningLink" :disabled="isLoading" variant="outline" size="lg" class="mt-4 px-8 py-4 border-[#FF5C16] border-[1px]"> + <Button :copy="getAccountCreateSigningLink" :disabled="isLoading || !createAccountNameOperation || !accountNameValid" variant="outline" size="lg" class="mt-4 px-8 py-4 border-[#FF5C16] border-[1px]"> <span class="text-md font-bold">Copy signing link</span> </Button> </div> diff --git a/src/components/sidebar/ToggleSidebar.vue b/src/components/sidebar/ToggleSidebar.vue index 69da26a271dd7cc3a54a6190abd155fa0e0eb135..43810742fe70a74a73d5e4a78554a7d9347a859a 100644 --- a/src/components/sidebar/ToggleSidebar.vue +++ b/src/components/sidebar/ToggleSidebar.vue @@ -7,7 +7,7 @@ const { toggleSidebar, open, isMobile } = useSidebar(); </script> <template> - <Button variant="ghost" size="xs" @click="toggleSidebar"> + <Button v-if="isMobile" variant="ghost" size="xs" @click="toggleSidebar"> <svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path style="fill: hsl(var(--foreground))" :d="open && !isMobile ? mdiMenuOpen : mdiMenuClose"></path> </svg> diff --git a/src/components/utilcards/ConfirmAccountUpdateCard.vue b/src/components/utilcards/ConfirmAccountUpdateCard.vue index 22b9094f1495561f7fe75faa5af457080317202a..a060a93853a245cb337af77e776d7abbdfaef49d 100644 --- a/src/components/utilcards/ConfirmAccountUpdateCard.vue +++ b/src/components/utilcards/ConfirmAccountUpdateCard.vue @@ -53,8 +53,7 @@ const updateAuthority = async() => { if (ownerKey.value) op.role("owner").add(ownerKey.value); tx.pushOperation(op); - const signature = await wallet.wallet!.signTransaction(tx, ownerKey.value ? "owner" : "active"); - tx.sign(signature); + await wallet.wallet!.signTransaction(tx, ownerKey.value ? "owner" : "active"); await wax.broadcast(tx); } catch (error) { toastError('Error updating authority', error); diff --git a/src/components/utilcards/ConfirmCreateAccountCard.vue b/src/components/utilcards/ConfirmCreateAccountCard.vue index 947bcdda42df3067461fee477cb01aab5df319b7..608b6e76389a6f3fe2943859b4e3c792ae939a0d 100644 --- a/src/components/utilcards/ConfirmCreateAccountCard.vue +++ b/src/components/utilcards/ConfirmCreateAccountCard.vue @@ -105,8 +105,7 @@ const createAccount = async() => { }); } } - const signature = await wallet.wallet!.signTransaction(tx, "active"); - tx.sign(signature); + await wallet.wallet!.signTransaction(tx, "active"); await wax.broadcast(tx); } catch (error) { toastError('Error creating account', error); diff --git a/src/components/utilcards/SignTransactionCard.vue b/src/components/utilcards/SignTransactionCard.vue index fe94e7554f3b635d8275203f18aa071b59561055..b120f751f86e7dbee3f1e5ef762e48f962053880 100644 --- a/src/components/utilcards/SignTransactionCard.vue +++ b/src/components/utilcards/SignTransactionCard.vue @@ -6,7 +6,7 @@ import { Textarea } from '@/components/ui/textarea'; import { Button } from '@/components/ui/button'; import { useWalletStore } from '@/stores/wallet.store'; import { getWax } from '@/stores/wax.store'; -import type { ITransactionBase, TRole } from '@hiveio/wax/vite'; +import type { ITransaction, TRole } from '@hiveio/wax/vite'; import { useRouter } from 'vue-router'; import { toastError } from '@/utils/parse-error'; @@ -36,7 +36,7 @@ const sign = async () => { const wax = await getWax(); - let tx: ITransactionBase; + let tx: ITransaction; try { tx = wax.createTransactionFromJson(inputData.value); @@ -54,7 +54,9 @@ const sign = async () => { // TODO: Handle "other" authority - outputData.value = await wallet.value!.signTransaction(tx, authorityLevel); + await wallet.value!.signTransaction(tx, authorityLevel); + + outputData.value = tx.toApi(); } catch (error) { toastError('Error signing transaction', error); } finally { @@ -98,7 +100,7 @@ onMounted(() => { <div class="my-4 space-x-4"> <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/> + <Textarea v-model="outputData" placeholder="Signed transaction" copy-enabled class="my-4" disabled/> <div class="my-4 space-x-4"> <Button :disabled="!outputData || isLoading" :loading="isBroadcasting" @click="broadcast">Broadcast signed transaction</Button> </div> diff --git a/src/utils/wallet/abstraction.ts b/src/utils/wallet/abstraction.ts index 6addbeec305c35616f19676f906c1f948d6a32ec..3bc3841fcf64eded89f2654386c3ef03ae41fe46 100644 --- a/src/utils/wallet/abstraction.ts +++ b/src/utils/wallet/abstraction.ts @@ -1,7 +1,7 @@ -import type { TPublicKey, TRole, ITransactionBase } from "@hiveio/wax/vite"; +import type { TPublicKey, TRole, ITransaction } from "@hiveio/wax/vite"; export interface Wallet { - signTransaction(transaction: ITransactionBase, role: TRole): Promise<string>; + signTransaction(transaction: ITransaction, role: TRole): Promise<void>; encrypt(buffer: string, recipient: TPublicKey): Promise<string>; decrypt(buffer: string): Promise<string>; } diff --git a/src/utils/wallet/keychain/index.ts b/src/utils/wallet/keychain/index.ts index 2c42db497ca865423b5d6690d2927ab125643ee1..a025a684848c2d554f16a2e77b69a716fc619449 100644 --- a/src/utils/wallet/keychain/index.ts +++ b/src/utils/wallet/keychain/index.ts @@ -1,4 +1,4 @@ -import type { TRole, TPublicKey, TAccountName, ITransactionBase } from "@hiveio/wax/vite"; +import type { TRole, TPublicKey, TAccountName, ITransaction } from "@hiveio/wax/vite"; import type { Wallet } from "../abstraction"; export const createKeychainWalletFor = (account: TAccountName) => { @@ -10,7 +10,7 @@ export class KeychainWallet implements Wallet { private readonly account: TAccountName ) {} - public async signTransaction(transaction: ITransactionBase, role: TRole): Promise<string> { + public async signTransaction(transaction: ITransaction, role: TRole): Promise<void> { const response = await new Promise((resolve, reject) => (window as any).hive_keychain.requestSignTx( this.account, JSON.parse(transaction.toLegacyApi()), @@ -23,7 +23,8 @@ export class KeychainWallet implements Wallet { } )) as any; - return response.result.signatures; + for(const signature of response.result.signatures) + transaction.sign(signature); } public async encrypt(buffer: string, recipient: TPublicKey): Promise<string> { diff --git a/src/utils/wallet/metamask/metamask.ts b/src/utils/wallet/metamask/metamask.ts index bfc8e5bcc569cb2fe8e54dbc60f01e61a01c4fb3..76f1d05b7be73a07c9a8a71e1c3e3f94cab06f40 100644 --- a/src/utils/wallet/metamask/metamask.ts +++ b/src/utils/wallet/metamask/metamask.ts @@ -1,7 +1,7 @@ import type { MetaMaskInpageProvider } from "@metamask/providers"; import { defaultSnapOrigin, defaultSnapVersion, isLocalSnap } from "./snap"; import type { Wallet } from "../abstraction"; -import type { TPublicKey, TRole, ITransactionBase } from "@hiveio/wax/vite"; +import type { TPublicKey, TRole, ITransaction } from "@hiveio/wax/vite"; export type MetamaskSnapData = { permissionName: string; @@ -35,10 +35,11 @@ export class MetamaskWallet implements Wallet { return this.provider.request(params ? { method, params } : { method }); } - public async signTransaction(transaction: ITransactionBase, role: TRole) { + public async signTransaction(transaction: ITransaction, role: TRole): Promise<void> { const response = await this.invokeSnap('hive_signTransaction', { transaction: transaction.toApi(), keys: [{ role }] }) as any; - return response.signatures[0]; + for(const signature of response.signatures) + transaction.sign(signature); } public async encrypt(buffer: string, recipient: TPublicKey): Promise<string> { diff --git a/src/utils/wallet/peakvault/index.ts b/src/utils/wallet/peakvault/index.ts index 98836cb71e692e8e6b3e6e4bb6d050717fb55e1f..6f885d84152d3e2082e4bd90d868713a4fc5ebff 100644 --- a/src/utils/wallet/peakvault/index.ts +++ b/src/utils/wallet/peakvault/index.ts @@ -1,5 +1,5 @@ -import type { TRole, TPublicKey, TAccountName, ITransactionBase } from "@hiveio/wax/vite"; +import type { TRole, TPublicKey, TAccountName, ITransaction } from "@hiveio/wax/vite"; import type { Wallet } from "../abstraction"; export const createPeakVaultWalletFor = (account: TAccountName) => { @@ -11,10 +11,11 @@ export class PeakVaultWallet implements Wallet { private readonly account: TAccountName ) {} - public async signTransaction(transaction: ITransactionBase, role: TRole): Promise<string> { + public async signTransaction(transaction: ITransaction, role: TRole): Promise<void> { const response = await (window as any).peakvault.requestSignTx(this.account, JSON.parse(transaction.toLegacyApi()), role); - return response.result.signatures[0]; + for(const signature of response.result.signatures) + transaction.sign(signature); } public async encrypt(buffer: string, recipient: TPublicKey): Promise<string> {