it-tools/src/tools/bip39-generator/bip39-generator.vue

151 lines
4.1 KiB
Vue
Raw Normal View History

2022-04-09 15:17:59 +02:00
<template>
2022-04-15 23:10:47 +02:00
<div>
<n-card>
2022-04-22 23:31:40 +02:00
<n-grid cols="3" x-gap="12">
2022-04-15 23:10:47 +02:00
<n-gi span="1">
<n-form-item label="Language:">
<n-select
v-model:value="language"
2022-04-22 23:31:40 +02:00
:options="Object.keys(languages).map((label) => ({ label, value: label }))"
2022-04-15 23:10:47 +02:00
/>
</n-form-item>
</n-gi>
<n-gi span="2">
<n-form-item
label="Entropy (seed):"
:feedback="entropyValidation.message"
:validation-status="entropyValidation.status"
>
<n-input-group>
2022-04-22 23:31:40 +02:00
<n-input v-model:value="entropy" placeholder="Your string..." />
2022-04-15 23:10:47 +02:00
<n-button @click="refreshEntropy">
<n-icon size="22">
<Refresh />
</n-icon>
</n-button>
<n-button @click="copyEntropy">
<n-icon size="22">
<Copy />
</n-icon>
</n-button>
</n-input-group>
</n-form-item>
</n-gi>
</n-grid>
<n-form-item
label="Passphrase (mnemonic):"
:feedback="mnemonicValidation.message"
:validation-status="mnemonicValidation.status"
>
<n-input-group>
<n-input
v-model:value="passphrase"
2022-04-22 23:31:40 +02:00
style="text-align: center; flex: 1"
2022-04-15 23:10:47 +02:00
placeholder="Your mnemonic..."
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
/>
2022-04-11 22:47:05 +02:00
2022-04-15 23:10:47 +02:00
<n-button @click="copyPassphrase">
2022-04-22 23:31:40 +02:00
<n-icon size="22" :component="Copy" />
2022-04-15 23:10:47 +02:00
</n-button>
</n-input-group>
</n-form-item>
</n-card>
</div>
2022-04-09 15:17:59 +02:00
</template>
<script setup lang="ts">
import { useCopy } from '@/composable/copy';
import { useValidation } from '@/composable/validation';
import { withDefaultOnError } from '@/utils/defaults';
2022-04-11 22:47:05 +02:00
import {
2022-04-22 23:31:40 +02:00
chineseSimplifiedWordList,
chineseTraditionalWordList,
czechWordList,
englishWordList,
entropyToMnemonic,
2022-04-22 23:31:40 +02:00
frenchWordList,
generateEntropy,
2022-04-22 23:31:40 +02:00
italianWordList,
japaneseWordList,
koreanWordList,
mnemonicToEntropy,
2022-04-22 23:31:40 +02:00
portugueseWordList,
spanishWordList,
} from '@it-tools/bip39';
import { Copy, Refresh } from '@vicons/tabler';
import { computed, ref } from 'vue';
2022-04-11 22:47:05 +02:00
const languages = {
2022-04-22 23:31:40 +02:00
English: englishWordList,
'Chinese simplified': chineseSimplifiedWordList,
'Chinese traditional': chineseTraditionalWordList,
Czech: czechWordList,
French: frenchWordList,
Italian: italianWordList,
Japanese: japaneseWordList,
Korean: koreanWordList,
Portuguese: portugueseWordList,
Spanish: spanishWordList,
};
2022-04-11 22:47:05 +02:00
2022-04-22 23:31:40 +02:00
const entropy = ref(generateEntropy());
const passphraseInput = ref('');
2022-04-11 22:47:05 +02:00
2022-04-22 23:31:40 +02:00
const language = ref<keyof typeof languages>('English');
2022-04-11 22:47:05 +02:00
const passphrase = computed({
2022-04-22 23:31:40 +02:00
get() {
try {
return entropyToMnemonic(entropy.value, languages[language.value]);
} catch (_) {
return passphraseInput.value;
}
},
set(value: string) {
passphraseInput.value = value;
entropy.value = withDefaultOnError(() => mnemonicToEntropy(value, languages[language.value]), '');
2022-04-22 23:31:40 +02:00
},
});
2022-04-09 15:17:59 +02:00
2022-04-11 22:47:05 +02:00
const entropyValidation = useValidation({
2022-04-22 23:31:40 +02:00
source: entropy,
rules: [
{
validator: (value) => value === '' || (value.length <= 32 && value.length >= 16 && value.length % 4 === 0),
message: 'Entropy length should be >= 16, <= 32 and be a multiple of 4',
},
{
validator: (value) => /^[a-fA-F0-9]*$/.test(value),
message: 'Entropy should be an hexadecimal string',
2022-04-22 23:31:40 +02:00
},
],
});
2022-04-11 22:47:05 +02:00
const mnemonicValidation = useValidation({
2022-04-22 23:31:40 +02:00
source: passphrase,
rules: [
{
validator: (value) => {
try {
mnemonicToEntropy(value, languages[language.value]);
2022-04-22 23:31:40 +02:00
return true;
} catch (_) {
return false;
2022-04-11 22:47:05 +02:00
}
2022-04-22 23:31:40 +02:00
},
message: 'Invalid mnemonic',
},
],
});
2022-04-11 22:47:05 +02:00
function refreshEntropy() {
2022-04-22 23:31:40 +02:00
entropy.value = generateEntropy();
2022-04-11 22:47:05 +02:00
}
2022-04-22 23:31:40 +02:00
const { copy: copyEntropy } = useCopy({ source: entropy, text: 'Entropy copied to the clipboard' });
const { copy: copyPassphrase } = useCopy({ source: passphrase, text: 'Passphrase copied to the clipboard' });
2022-04-09 15:17:59 +02:00
</script>