Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1342 threshold nicknames #1544

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions front-end/src/main/services/localUser/complexKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,13 @@ export const deleteComplexKey = async (id: string) => {
});
};

export const updateComplexKey = async (id: string, newKeyListBytes: Uint8Array, nickname?: string) => {
export const updateComplexKey = async (id: string, newKeyListBytes?: Uint8Array, nickname?: string) => {
const prisma = getPrismaClient();
let newProtobufEncoded;

const newProtobufEncoded = Buffer.from(newKeyListBytes).toString('hex');
if (newKeyListBytes) {
newProtobufEncoded = Buffer.from(newKeyListBytes).toString('hex');
}

await prisma.complexKey.updateMany({
where: {
Expand Down
2 changes: 1 addition & 1 deletion front-end/src/preload/localUser/complexKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default {
getComplexKey: (userId: string, keyListBytes: Uint8Array): Promise<ComplexKey> =>
ipcRenderer.invoke('complexKeys:getComplexKey', userId, keyListBytes),
delete: (id: string): Promise<ComplexKey[]> => ipcRenderer.invoke('complexKeys:delete', id),
update: (id: string, newKeyListBytes: Uint8Array, nickname?: string): Promise<ComplexKey> =>
update: (id: string, newKeyListBytes?: Uint8Array, nickname?: string): Promise<ComplexKey> =>
ipcRenderer.invoke('complexKeys:update', id, newKeyListBytes, nickname),
},
};
16 changes: 3 additions & 13 deletions front-end/src/renderer/components/ComplexKey/ComplexKey.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { onBeforeMount, ref } from 'vue';
import { Key, KeyList } from '@hashgraph/sdk';

import ComplexKeyThreshold from '@renderer/components/ComplexKey/ComplexKeyThreshold.vue';
Expand All @@ -10,7 +10,7 @@ const props = defineProps<{
}>();

/* Emits */
const emit = defineEmits(['update:modelKey', 'update:nickname', 'listLoaded']);
const emit = defineEmits(['update:modelKey']);

/* State */
const keyList = ref<KeyList>(new KeyList());
Expand All @@ -25,16 +25,8 @@ const handleKeyListRemove = () => {
emit('update:modelKey', keyList.value);
};

function handleNicknameChange(nickname: string) {
emit('update:nickname', nickname);
}

function handleListLoaded(listId: string) {
emit('listLoaded', listId);
}

/* Hooks */
onMounted(() => {
onBeforeMount(() => {
if (props.modelKey instanceof KeyList) {
keyList.value = props.modelKey;
}
Expand All @@ -44,8 +36,6 @@ onMounted(() => {
<ComplexKeyThreshold
v-model:key-list="keyList"
@update:key-list="handleKeyListChange"
@update:nickname="handleNicknameChange"
@list-loaded="handleListLoaded"
:on-remove-key-list="handleKeyListRemove"
:depth="'0'"
/>
Expand Down
68 changes: 24 additions & 44 deletions front-end/src/renderer/components/ComplexKey/ComplexKeyModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@ import { computed, ref, watch } from 'vue';

import { Key, KeyList } from '@hashgraph/sdk';

import { encodeKey, isKeyListValid, isUserLoggedIn } from '@renderer/utils';
import { isKeyListValid } from '@renderer/utils';

import AppButton from '@renderer/components/ui/AppButton.vue';
import AppModal from '@renderer/components/ui/AppModal.vue';
import AppCustomIcon from '@renderer/components/ui/AppCustomIcon.vue';
import ComplexKey from '@renderer/components/ComplexKey/ComplexKey.vue';
import KeyStructure from '@renderer/components/KeyStructure.vue';
import {
addComplexKey,
getComplexKey,
updateComplexKey,
} from '@renderer/services/complexKeysService';
import useUserStore from '@renderer/stores/storeUser';
import useNicknamesStore from '@renderer/stores/storeNicknames';

/* Props */
const props = defineProps<{
Expand All @@ -24,18 +19,15 @@ const props = defineProps<{
onSaveComplexKey?: () => void;
}>();

const nicknames = useNicknamesStore();

/* Emits */
const emit = defineEmits(['update:show', 'update:modelKey']);

/* Stores */
const user = useUserStore();

/* State */
const currentKey = ref<Key | null>(props.modelKey);
const errorModalShow = ref(false);
const summaryMode = ref(false);
const nickname = ref('');
const listId = ref('');

/* Computed */
const currentKeyInvalid = computed(
Expand All @@ -62,39 +54,32 @@ const handleSaveComplexKeyButtonClick = () => {
}
};

const handleSaveButtonClick = async () => {
if (!isUserLoggedIn(user.personal)) {
throw new Error('User is not logged in');
}

const handleDoneButtonClick = async () => {
if (currentKeyInvalid.value) {
errorModalShow.value = true;
return;
}

if (nickname.value && currentKey.value instanceof KeyList) {
const list = await getComplexKey(user.personal.id, currentKey.value);
const keyListBytes = encodeKey(currentKey.value);
if (list && !listId.value) {
await updateComplexKey(list.id, keyListBytes, nickname.value);
} else if (listId.value) {
await updateComplexKey(listId.value, keyListBytes, nickname.value);
listId.value = '';
} else {
await addComplexKey(user.personal.id, keyListBytes, nickname.value);
}
}

emit('update:modelKey', currentKey.value, nickname.value ? true : false);
emit('update:modelKey', currentKey.value);
emit('update:show', false);
};

function handleNicknameUpdate(newNickname: string) {
nickname.value = newNickname;
async function handleExit() {
await nicknames.clearNicknames();
emit('update:show', false);
}

function handleListLoaded(id: string) {
listId.value = id;
function handleSummaryEdit() {
summaryMode.value = !summaryMode.value;

if (summaryMode.value) {
if (currentKeyInvalid.value) {
errorModalShow.value = true;
return;
}

emit('update:modelKey', currentKey.value);
}
}

/* Watchers */
Expand All @@ -111,9 +96,9 @@ const modalContentContainerStyle = { padding: '0 10%', height: '80%' };
<template>
<AppModal :show="show" @update:show="handleShowUpdate" class="full-screen-modal">
<div class="p-5 h-100">
<form @submit.prevent="handleSaveButtonClick" class="h-100">
<form @submit.prevent="handleDoneButtonClick" class="h-100">
<div>
<i class="bi bi-x-lg cursor-pointer" @click="$emit('update:show', false)"></i>
<i class="bi bi-x-lg cursor-pointer" @click="handleExit"></i>
</div>
<h1 class="text-title text-semi-bold text-center">Complex Key</h1>
<div :style="modalContentContainerStyle">
Expand All @@ -122,7 +107,7 @@ const modalContentContainerStyle = { padding: '0 10%', height: '80%' };
color="borderless"
type="button"
class="text-body"
@click="summaryMode = !summaryMode"
@click="handleSummaryEdit"
>{{ summaryMode ? 'Edit Mode' : 'View Summary' }}</AppButton
>
<AppButton
Expand All @@ -145,12 +130,7 @@ const modalContentContainerStyle = { padding: '0 10%', height: '80%' };
<div v-if="show" class="mt-5 h-100 overflow-auto">
<Transition name="fade" :mode="'out-in'">
<div v-if="!summaryMode">
<ComplexKey
:model-key="currentKey"
@update:model-key="handleComplexKeyUpdate"
@update:nickname="handleNicknameUpdate"
@list-loaded="handleListLoaded"
/>
<ComplexKey :model-key="currentKey" @update:model-key="handleComplexKeyUpdate" />
</div>
<div v-else>
<KeyStructure
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<script setup lang="ts">
import { onBeforeMount, ref, toRaw } from 'vue';
import { onBeforeMount, ref } from 'vue';
import { Key, KeyList, PublicKey } from '@hashgraph/sdk';

import useUserStore from '@renderer/stores/storeUser';
import useContactsStore from '@renderer/stores/storeContacts';
import useNicknamesStore from '@renderer/stores/storeNicknames';

import { useToast } from 'vue-toast-notification';

import { decodeKeyList, isPublicKeyInKeyList } from '@renderer/utils';
import { isPublicKeyInKeyList, isUserLoggedIn } from '@renderer/utils';
import * as ush from '@renderer/utils/userStoreHelpers';

import AppButton from '@renderer/components/ui/AppButton.vue';
import AppInput from '@renderer/components/ui/AppInput.vue';
import AppPublicKeyInput from '@renderer/components/ui/AppPublicKeyInput.vue';
import ComplexKeyAddPublicKeyModal from '@renderer/components/ComplexKey/ComplexKeyAddPublicKeyModal.vue';
import ComplexKeySelectAccountModal from '@renderer/components/ComplexKey/ComplexKeySelectAccountModal.vue';
import { getComplexKeys } from '@renderer/services/complexKeysService';

/* Props */
const props = defineProps<{
Expand All @@ -25,11 +25,12 @@ const props = defineProps<{
}>();

/* Emits */
const emit = defineEmits(['update:keyList', 'update:nickname', 'listLoaded']);
const emit = defineEmits(['update:keyList']);

/* Stores */
const user = useUserStore();
const contacts = useContactsStore();
const nicknames = useNicknamesStore();

/* Composables */
const toast = useToast();
Expand All @@ -39,6 +40,7 @@ const areChildrenShown = ref(true);
const addPublicKeyModalShown = ref(false);
const selectAccountModalShown = ref(false);
const nickname = ref('');
const keyId = ref('');

/* Handlers */
const handleThresholdChange = (e: Event) => {
Expand All @@ -52,8 +54,8 @@ const handleSelectAccount = (key: Key) => {
if (key instanceof PublicKey && isPublicKeyInKeyList(key, keys)) {
toast.error('Public key already exists in the key list');
} else {
const keys = props.keyList.toArray();
keys.push(key);
let keys = props.keyList.toArray();
keys = [...keys, key];
emitNewKeyList(keys, props.keyList.threshold);
selectAccountModalShown.value = false;
}
Expand All @@ -63,11 +65,11 @@ const handleAddPublicKey = (publicKeys: PublicKey[]) => {
const publicKeysInKeyList = new KeyList(
props.keyList.toArray().filter(key => key instanceof PublicKey),
);
const keys = props.keyList.toArray();
let keys = props.keyList.toArray();

for (const publicKey of publicKeys) {
if (!isPublicKeyInKeyList(publicKey, publicKeysInKeyList)) {
keys.push(publicKey);
keys = [...keys, publicKey];
} else {
toast.error(`${publicKey.toStringRaw()} already exists in the key list`);
}
Expand All @@ -84,8 +86,8 @@ const handleRemovePublicKey = (publicKey: PublicKey) => {
};

const handleAddThreshold = () => {
const keys = props.keyList.toArray();
keys.push(new KeyList([]));
let keys = props.keyList.toArray();
keys = [...keys, new KeyList([])];
emitNewKeyList(keys, props.keyList.threshold);
};

Expand All @@ -101,35 +103,28 @@ const handleKeyListUpdate = (index: number, newKeyList: KeyList) => {
newParentKeyList.splice(index, 1, newKeyList);

emit('update:keyList', newParentKeyList);
nicknames.updateKey(nickname.value, newParentKeyList, keyId.value);
};

function handleNicknameChange() {
emit('update:nickname', nickname.value);
function handleUpdateNickname(value: string) {
nicknames.updateNickname(value, nickname.value, props.keyList);
nickname.value = value;
}

/* Funtions */
function emitNewKeyList(keys: Key[], threshold: number | null) {
const newKeyList = new KeyList(keys, threshold);
emit('update:keyList', newKeyList);
nicknames.updateKey(nickname.value, newKeyList, keyId.value);
}

/* Hooks */
onBeforeMount(async () => {
if (!ush.isUserLoggedIn(user.personal)) {
if (!isUserLoggedIn(user.personal)) {
throw new Error('User is not logged in');
}

const keyLists = await getComplexKeys(user.personal.id);

for (const keyList of keyLists) {
const list = decodeKeyList(keyList.protobufEncoded).toArray();
const propList = toRaw(props.keyList).toArray();

if (JSON.stringify(list) === JSON.stringify(propList)) {
nickname.value = keyList.nickname;
emit('listLoaded', keyList.id);
}
}
[nickname.value, keyId.value] = await nicknames.getNickName(props.keyList);
});
</script>
<template>
Expand All @@ -150,14 +145,13 @@ onBeforeMount(async () => {
@click="areChildrenShown = !areChildrenShown"
></span>
</Transition>
<!-- <p class="text-small text-semi-bold ms-3">Threshold</p> -->
<AppInput
v-model="nickname"
:model-value="nickname"
@update:model-value="handleUpdateNickname"
size="small"
class="ms-5"
style="width: 250px"
placeholder="Threshold"
@change="handleNicknameChange"
/>
<div class="ms-3">
<select
Expand Down Expand Up @@ -227,7 +221,7 @@ onBeforeMount(async () => {
</div>
<Transition name="fade" mode="out-in">
<div v-show="areChildrenShown">
<template v-for="(key, i) in keyList.toArray()" :key="key.toString()">
<template v-for="(key, i) in keyList.toArray()" :key="`${i} + ${depth || 'top'}`">
<template v-if="key instanceof PublicKey && true">
<div class="key-node-wrapper">
<div class="key-node" :path="`${depth || 0}-${i}`">
Expand Down
Loading
Loading