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

Start custom message keysign #772

Merged
merged 9 commits into from
Jan 15, 2025
4 changes: 4 additions & 0 deletions frontend/src/i18n/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,4 +640,8 @@ export const de = {
signature: 'Unterschrift',
signing_method: 'Signiermethode',
message_to_sign: 'Zu unterzeichnende Nachricht',
sign_custom_message: 'Benutzerdefinierte Nachricht signieren',
sign_message: 'Nachricht signieren',
method_required: 'Signaturmethode ist erforderlich',
message_required: 'Nachricht ist erforderlich',
};
4 changes: 4 additions & 0 deletions frontend/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ export const en = {
secureVault: 'Secure Vault',
active: 'Active',
sign: 'Sign',
sign_custom_message: 'Sign custom message',
sign_message: 'Sign message',
action: 'Action',
fast_vault_setup_prop_0: 'Single Device Setup',
fast_vault_setup_prop_1: 'Transaction Alerts & Policies',
Expand Down Expand Up @@ -627,6 +629,8 @@ export const en = {
},
signing_method: 'Signing Method',
message_to_sign: 'Message to sign',
method_required: 'Signing method is required',
message_required: 'Message is required',
saving_vault: 'Saving Vault...',
scan_with_devices: 'Scan with devices to join the vault generation',
scan_with_devices_to_sign:
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/i18n/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,4 +640,8 @@ export const es = {
signature: 'Firma',
signing_method: 'Método de firma',
message_to_sign: 'Mensaje para firmar',
sign_custom_message: 'Firmar mensaje personalizado',
sign_message: 'Firmar mensaje',
method_required: 'Se requiere método de firma',
message_required: 'El mensaje es obligatorio',
};
4 changes: 4 additions & 0 deletions frontend/src/i18n/locales/hr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -618,4 +618,8 @@ export const hr = {
signature: 'Potpis',
signing_method: 'Način potpisivanja',
message_to_sign: 'Poruka za potpisivanje',
sign_custom_message: 'Potpišite prilagođenu poruku',
sign_message: 'Potpišite poruku',
method_required: 'Potreban je način potpisivanja',
message_required: 'Poruka je obavezna',
};
4 changes: 4 additions & 0 deletions frontend/src/i18n/locales/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -636,4 +636,8 @@ export const it = {
signature: 'Firma',
signing_method: 'Metodo di firma',
message_to_sign: 'Messaggio da firmare',
sign_custom_message: 'Firma messaggio personalizzato',
sign_message: 'Messaggio del segno',
method_required: 'È richiesto il metodo di firma',
message_required: 'Il messaggio è obbligatorio',
};
4 changes: 4 additions & 0 deletions frontend/src/i18n/locales/pt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -631,4 +631,8 @@ export const pt = {
signature: 'Assinatura',
signing_method: 'Método de assinatura',
message_to_sign: 'Mensagem para assinar',
sign_custom_message: 'Assinar mensagem personalizada',
sign_message: 'Assinar mensagem',
method_required: 'O método de assinatura é obrigatório',
message_required: 'Mensagem é necessária',
};
17 changes: 17 additions & 0 deletions frontend/src/lib/ui/icons/SignatureIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const SignatureIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="lucide lucide-signature"
>
<path d="m21 17-2.156-1.868A.5.5 0 0 0 18 15.5v.5a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1c0-2.545-3.991-3.97-8.5-4a1 1 0 0 0 0 5c4.153 0 4.745-11.295 5.708-13.5a2.5 2.5 0 1 1 3.31 3.284" />
<path d="M3 21h18" />
</svg>
);
14 changes: 14 additions & 0 deletions frontend/src/lib/utils/getRecordUnionValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { getRecordKeys } from './record/getRecordKeys';

export function getRecordUnionValue<U, K extends string>(
value: U,
key: K
): Extract<U, Record<K, unknown>>[K] {
const keys = getRecordKeys(value as Record<string, unknown>);

if (!keys.includes(key)) {
throw new Error(`Key "${key}" not found in record union`);
}

return (value as Extract<U, Record<K, unknown>>)[key];
}
12 changes: 5 additions & 7 deletions frontend/src/navigation/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { KeysignMessagePayload } from '../chain/keysign/KeysignMessagePayload';
import { KeygenMessage } from '../gen/vultisig/keygen/v1/keygen_message_pb';
import { ReshareMessage } from '../gen/vultisig/keygen/v1/reshare_message_pb';
import {
KeysignMessage,
KeysignPayload,
} from '../gen/vultisig/keysign/v1/keysign_message_pb';
import { KeysignMessage } from '../gen/vultisig/keysign/v1/keysign_message_pb';
import { addQueryParams } from '../lib/utils/query/addQueryParams';
import { withoutUndefinedFields } from '../lib/utils/record/withoutUndefinedFields';
import { Chain } from '../model/chain';
Expand Down Expand Up @@ -53,6 +51,7 @@ export const appPaths = {
termsOfService: '/vault/settings/terms-of-service',
vaultFAQ: '/vault/settings/faq',
swap: '/vault/item/swap',
signCustomMessage: '/vault/sign-custom-message',
registerForAirdrop: '/register-for-airdrop',
onboarding: '/onboarding',
createVaultFolder: '/vault/create-folder',
Expand Down Expand Up @@ -81,11 +80,10 @@ export type AppPathParams = {

export type AppPathState = {
keysign: {
keysignPayload: KeysignPayload;
keysignAction?: 'send' | 'deposit';
keysignPayload: KeysignMessagePayload;
};
fastKeysign: {
keysignPayload: KeysignPayload;
keysignPayload: KeysignMessagePayload;
};
joinKeysign: { vaultId: string; keysignMsg: KeysignMessage };
joinKeygen: {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/pages/edItVault/EditVaultPage.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const TextWrapper = styled.div`
export const IconWrapper = styled.div`
align-self: center;
height: 30px;
font-size: 24px;
`;

export const AutoCenteredTitle = styled(Text)`
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/pages/edItVault/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import BackupIcon from '../../lib/ui/icons/BackupIcon';
import { InfoIcon } from '../../lib/ui/icons/InfoIcon';
import ReshareIcon from '../../lib/ui/icons/ReshareIcon';
import { SignatureIcon } from '../../lib/ui/icons/SignatureIcon';
import SquareAndPencilIcon from '../../lib/ui/icons/SquareAndPencilIcon';
import TrashIcon from '../../lib/ui/icons/TrashIcon';
import { TextColor } from '../../lib/ui/text';
Expand Down Expand Up @@ -39,6 +40,12 @@ export const editVaultSettingsItems: SettingItem[] = [
icon: ReshareIcon,
path: 'reshareVault',
},
{
titleKey: 'sign',
subtitleKey: 'sign_custom_message',
icon: SignatureIcon,
path: 'signCustomMessage',
},
{
titleKey: 'vault_setting_edit_vault_delete_title',
subtitleKey: 'vault_setting_edit_vault_delete_subtitle',
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { VaultPage } from './vault/components/VaultPage';
import { DepositPage } from './vault/deposit/DepositPage';
import { ImportVaultFromFilePage } from './vault/import/components/ImportVaultFromFilePage';
import { JoinKeygenPage } from './vault/keygen/join/JoinKeygenPage';
import { SignCustomMessagePage } from './vault/keysign/customMessage/SignCustomMessagePage';
import { JoinKeysignPage } from './vault/keysign/join/JoinKeysignPage';
import { StartFastKeysignPage } from './vault/keysign/start/fast/StartFastKeysignPage';
import { StartKeysignPage } from './vault/keysign/start/StartKeysignPage';
Expand Down Expand Up @@ -366,6 +367,10 @@ export const router = createBrowserRouter([
</ActiveVaultGuard>
),
},
{
path: appPaths.signCustomMessage,
element: <SignCustomMessagePage />,
},
],
},
]);
32 changes: 0 additions & 32 deletions frontend/src/utils/QRGen.ts

This file was deleted.

4 changes: 3 additions & 1 deletion frontend/src/vault/deposit/DepositConfirmButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ export const DepositConfirmButton = ({
}

navigate(type === 'fast' ? 'fastKeysign' : 'keysign', {
state: { keysignPayload, keysignAction: 'deposit' },
state: {
keysignPayload: { keysign: keysignPayload },
},
});
};

Expand Down
12 changes: 9 additions & 3 deletions frontend/src/vault/keysign/components/StartKeysignPrompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ export const StartKeysignPrompt = ({
onClick={() => {
navigate('fastKeysign', {
state: {
keysignPayload,
keysignPayload: {
keysign: keysignPayload,
},
},
});
}}
Expand All @@ -42,7 +44,9 @@ export const StartKeysignPrompt = ({
onClick={() => {
navigate('keysign', {
state: {
keysignPayload,
keysignPayload: {
keysign: keysignPayload,
},
},
});
}}
Expand All @@ -59,7 +63,9 @@ export const StartKeysignPrompt = ({
onClick={() => {
navigate('keysign', {
state: {
keysignPayload,
keysignPayload: {
keysign: keysignPayload,
},
},
});
}}
Expand Down
70 changes: 70 additions & 0 deletions frontend/src/vault/keysign/customMessage/SignCustomMessagePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { CustomMessagePayload } from '../../../gen/vultisig/keysign/v1/custom_message_payload_pb';
import { Button } from '../../../lib/ui/buttons/Button';
import { getFormProps } from '../../../lib/ui/form/utils/getFormProps';
import { TextInput } from '../../../lib/ui/inputs/TextInput';
import { VStack } from '../../../lib/ui/layout/Stack';
import { useAppNavigate } from '../../../navigation/hooks/useAppNavigate';
import { FlowPageHeader } from '../../../ui/flow/FlowPageHeader';
import { PageContent } from '../../../ui/page/PageContent';
import { WithProgressIndicator } from '../shared/WithProgressIndicator';

export const SignCustomMessagePage = () => {
const { t } = useTranslation();

const navigate = useAppNavigate();

const [method, setMethod] = useState('');
const [message, setMessage] = useState('');

const isDisabled = useMemo(() => {
if (!method) return t('method_required');
if (!message) return t('message_required');
}, [method, message, t]);

return (
<>
<FlowPageHeader title={t('sign_message')} />
<PageContent
as="form"
{...getFormProps({
onSubmit: () => {
navigate('keysign', {
state: {
keysignPayload: {
custom: new CustomMessagePayload({
method,
message,
}),
},
},
});
},
isDisabled,
})}
>
<WithProgressIndicator value={0.2}>
<VStack gap={20}>
<TextInput
label={t('method')}
value={method}
onValueChange={setMethod}
placeholder={t('signing_method')}
/>
<TextInput
label={t('message')}
value={message}
onValueChange={setMessage}
placeholder={t('message_to_sign')}
/>
</VStack>
</WithProgressIndicator>
<Button isDisabled={isDisabled} type="submit">
{t('sign')}
</Button>
</PageContent>
</>
);
};
9 changes: 9 additions & 0 deletions frontend/src/vault/keysign/customMessage/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { TssKeysignType } from '../../../chain/keysign/TssKeysignType';
import { Chain } from '../../../model/chain';

const tssType: TssKeysignType = 'ecdsa';

export const customMessageConfig = {
chain: Chain.Ethereum,
tssType,
};
Loading
Loading