Skip to content

Commit

Permalink
Merge pull request #70 from dl-solarity/feature/convertors
Browse files Browse the repository at this point in the history
merged feature/convertors into master
  • Loading branch information
lilbonekit committed Sep 23, 2024
2 parents 1223062 + b147ded commit 4127683
Show file tree
Hide file tree
Showing 35 changed files with 829 additions and 72 deletions.
1 change: 1 addition & 0 deletions assets/icons/square-root-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions components/AppCopy.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<template>
<div class="app-copy">
<slot />
<!-- TODO: Refactor condition to avoid "value || ' '" in components -->
<button v-if="String(props.value)" type="button" @click="handleCopy">
<app-icon
class="app-copy__icon"
Expand Down
10 changes: 10 additions & 0 deletions components/ToolsSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ const navLinks = computed(() => [
icon: ICON_NAMES.locationMarker,
route: { name: ROUTE_NAMES.addressUtils },
},
{
title: t('tools-sidebar.constants'),
icon: ICON_NAMES.squareRoot,
route: { name: ROUTE_NAMES.constants },
},
{
title: t('tools-sidebar.ecrecover'),
icon: ICON_NAMES.checkCircle,
route: { name: ROUTE_NAMES.ecrecover },
},
])
const { width: windowWidth } = useWindowSize()
Expand Down
1 change: 1 addition & 0 deletions composables/use-form-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ export const useFormValidation = (
getFieldErrorMessage,
touchField,
isFormValid,
validationController,
}
}
2 changes: 2 additions & 0 deletions constants/bytes.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const ZERO_BYTES_32 =
'0x0000000000000000000000000000000000000000000000000000000000000000'
1 change: 1 addition & 0 deletions constants/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './numbers.constant'
export * from './bytes.constant'
1 change: 1 addition & 0 deletions enums/icon-names.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ export enum ICON_NAMES {
refresh = 'refresh',
xCircle = 'x-circle',
x = 'x',
squareRoot = 'square-root',
}
1 change: 1 addition & 0 deletions enums/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './ethereum-types.enum'
export * from './icon-names.enum'
export * from './route-names.enum'
export * from './window-breakpoints.enum'
export * from './period.enum'
17 changes: 17 additions & 0 deletions enums/period.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export enum PERIOD_IDS {
seconds = 's',
minutes = 'min',
hours = 'h',
days = 'd',
weeks = 'w',
months = 'mon',
years = 'y',
}

export enum PERIOD_CONSTANTS {
secondsInHour = 3600,
hoursInDay = 24,
daysInWeek = 7,
daysInMonth = 30,
daysInYear = 360,
}
6 changes: 6 additions & 0 deletions enums/route-names.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ export enum ROUTE_NAMES {
unixEpoch = 'unix-epoch',
unixEpochDate = 'unix-epoch-date',
unixEpochTimestamp = 'unix-epoch-timestamp',
unixEpochDuration = 'unix-epoch-duration',
converter = 'converter',
converterUnit = 'converter-unit',
converterNumber = 'converter-number',
converterAscii = 'converter-ascii',
hashFunction = 'hash-function',
hashFunctionKeccak256Id = 'hash-function-keccak256-id',
hashFunctionSha256Id = 'hash-function-sha256-id',
Expand All @@ -18,4 +20,8 @@ export enum ROUTE_NAMES {
addressUtilsCommonAddresses = 'address-utils-common-addresses',
addressUtilsCreate = 'address-utils-create',
addressUtilsCreate2 = 'address-utils-create2',
constants = 'constants',
constantsBytes = 'constants-bytes',
ecrecover = 'ecrecover',
ecrecoverVerify = 'ecrecover-verify',
}
35 changes: 35 additions & 0 deletions fields/TextareaField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
{{ label }}
</label>
<div class="textarea-field__textarea-wrp">
<div
v-if="hasLeftNode"
ref="nodeLeftWrp"
class="textarea-field__node-left-wrp"
>
<slot v-if="$slots.nodeLeft" name="nodeLeft" />
</div>
<textarea
ref="textareaElement"
class="textarea-field__textarea"
Expand Down Expand Up @@ -105,6 +112,7 @@ const slots = useSlots()
const uid = uuidv4()
const textareaElement = ref<HTMLTextAreaElement | null>(null)
const nodeRightWrp = ref<HTMLDivElement | null>(null)
const nodeLeftWrp = ref<HTMLDivElement | null>(null)
const isDisabled = computed(() =>
['', 'disabled', true].includes(attrs.disabled as string | boolean),
Expand All @@ -122,6 +130,8 @@ const hasRightNode = computed<boolean>(() =>
Boolean(slots.nodeRight || props.isClearable || props.errorMessage),
)
const hasLeftNode = computed<boolean>(() => Boolean(slots.nodeLeft))
const listeners = computed(() => ({
input: (event: Event) => {
const eventTarget = event.target as HTMLTextAreaElement
Expand All @@ -132,6 +142,7 @@ const listeners = computed(() => ({
const textareaClasses = computed(() => [
'textarea-field',
...(hasRightNode.value ? ['textarea-field--node-right'] : []),
...(hasLeftNode.value ? ['textarea-field--node-left'] : []),
...(isDisabled.value ? ['textarea-field--disabled'] : []),
...(isReadonly.value ? ['textarea-field--readonly'] : []),
...(props.errorMessage ? ['textarea-field--error'] : []),
Expand Down Expand Up @@ -183,6 +194,15 @@ onMounted(() => {
}px + var(--field-padding-right) * 2)`,
)
}
if (slots?.nodeLeft && nodeLeftWrp.value) {
textareaElement.value?.style.setProperty(
'padding-left',
`calc(${
nodeLeftWrp.value?.offsetWidth || OFFSET_WIDTH
}px + var(--field-padding-right) * 2)`,
)
}
})
</script>

Expand Down Expand Up @@ -250,6 +270,10 @@ $z-index-side-nodes: 1;
padding-right: calc(var(--field-padding-right) * 3);
}
.textarea-field--node-left & {
padding-left: calc(var(--field-padding-left) * 3);
}
.textarea-field--error.textarea-field--primary & {
border-color: var(--field-error);
}
Expand Down Expand Up @@ -279,6 +303,17 @@ $z-index-side-nodes: 1;
gap: toRem(8);
}
.textarea-field__node-left-wrp {
position: absolute;
top: 50%;
left: var(--field-padding-left);
transform: translateY(-50%);
color: inherit;
z-index: $z-index-side-nodes;
display: flex;
gap: toRem(8);
}
.textarea-field__icon {
max-width: toRem(24);
max-height: toRem(24);
Expand Down
84 changes: 84 additions & 0 deletions forms/AsciiConverterForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<template>
<form class="ascii-converter-form">
<div class="ascii-converter-form__input">
<h3>{{ $t('ascii-converter-form.input-title') }}</h3>
<textarea-field
v-for="(value, key) in form"
size="small"
:model-value="value"
:key="key"
:label="$t(`ascii-converter-form.${key}-label`)"
:placeholder="$t(`ascii-converter-form.${key}-placeholder`)"
:error-message="getFieldErrorMessage(key)"
@update:model-value="formatInputs($event, key)"
@blur="touchField(key)"
>
<template #nodeLeft>
<!-- value || ' ' to keep the copy-button visible in input -->
<app-copy :value="value || ' '" />
</template>
</textarea-field>
</div>
</form>
</template>

<script lang="ts" setup>
import { AppCopy } from '#components'
import { useFormValidation } from '@/composables'
import { TextareaField } from '@/fields'
import { hexadecimal } from '@/helpers'
import { isEmpty } from 'lodash-es'
import { reactive } from 'vue'
import { hexToASCII, asciiToHex } from '@/helpers'
type AsciiConverterForm = {
hexadecimal: string
ascii: string
}
type AsciiConverterFormKeys = keyof AsciiConverterForm
const form = reactive<AsciiConverterForm>({
hexadecimal: '',
ascii: '',
})
const { getFieldErrorMessage, touchField, isFormValid } = useFormValidation(
form,
{
hexadecimal: { hexadecimal },
ascii: {},
},
)
const formatInputs = (value: string | number, key: AsciiConverterFormKeys) => {
form[key] = String(value)
const formKeys = Object.keys(form) as Array<AsciiConverterFormKeys>
const filteredKeys = formKeys.filter(_key => _key !== key)
const formattedValue = String(value).trim()
if (isEmpty(formattedValue) || !isFormValid()) {
for (key of filteredKeys) form[key] = ''
return
}
switch (key) {
case 'hexadecimal':
form.ascii = hexToASCII(form.hexadecimal)
break
case 'ascii':
form.hexadecimal = asciiToHex(form.ascii)
break
}
}
</script>

<style lang="scss" scoped>
.ascii-converter-form {
@include solidity-tools-form;
}
.ascii-converter-form__input {
@include solidity-tools-form-part;
}
</style>
35 changes: 11 additions & 24 deletions forms/CommonAddressesForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,33 @@
<form class="common-addresses-form" @submit.prevent>
<div class="common-addresses-form__input">
<h3>{{ $t('common-addresses-form.input-title') }}</h3>
<template v-for="(_, key) in form" :key="key">
<template v-for="(value, key) in form" :key="key">
<div v-if="key === 'randomAddress'">
<div class="common-addresses-form__label-wrp">
<label
class="common-addresses-form__label"
:for="randomAddressInputFieldUid"
>
<label class="common-addresses-form__label">
{{ $t(`common-addresses-form.${key}-label`) }}
</label>
<button
v-if="key === 'randomAddress'"
@click="form.randomAddress = generateRandomAddress()"
>
<button v-if="key === 'randomAddress'" @click="updateRandomAddress">
<app-icon
class="common-addresses-form__btn-icon"
:name="$icons.refresh"
/>
</button>
</div>
<input-field
readonly
:model-value="form[key]"
:uid="randomAddressInputFieldUid"
>
<input-field readonly :model-value="value">
<template #nodeLeft>
<app-copy :value="form[key]" />
<app-copy :value="value" />
</template>
</input-field>
</div>
<input-field
v-else
readonly
:label="$t(`common-addresses-form.${key}-label`)"
:model-value="form[key]"
:model-value="value"
>
<template #nodeLeft>
<app-copy :value="form[key]" />
<app-copy :value="value" />
</template>
</input-field>
</template>
Expand All @@ -50,22 +40,19 @@
import { AppCopy, AppIcon } from '#components'
import { InputField } from '@/fields'
import { Wallet } from 'ethers'
import { v4 as uuidv4 } from 'uuid'
import { onMounted, reactive } from 'vue'
import { reactive } from 'vue'
const randomAddressInputFieldUid = `input-field--${uuidv4()}`
const generateRandomAddress = (): string => Wallet.createRandom().address
const updateRandomAddress = () => {
form.randomAddress = generateRandomAddress()
}
const form = reactive({
zeroAddress: '0x0000000000000000000000000000000000000000',
allFsAddress: '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF',
allEsAddress: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
randomAddress: generateRandomAddress(),
})
onMounted(() => {
form.randomAddress = generateRandomAddress()
})
</script>

<style lang="scss" scoped>
Expand Down
Loading

0 comments on commit 4127683

Please sign in to comment.