diff --git a/src/components/Ui/UiInput.vue b/src/components/Ui/UiInput.vue index 538f3ffc..ff06b463 100644 --- a/src/components/Ui/UiInput.vue +++ b/src/components/Ui/UiInput.vue @@ -9,6 +9,7 @@ const props = defineProps<{ additionalInputClass?: string; focusOnMount?: boolean; readonly?: boolean; + quickFix?(): void; }>(); const emit = defineEmits(['update:modelValue', 'blur']); @@ -64,13 +65,22 @@ onMounted(() => {
- {{ error || '' }} + {{ error || '' }} + +
diff --git a/src/helpers/utils.ts b/src/helpers/utils.ts index 1b5b75d0..c9e1829a 100644 --- a/src/helpers/utils.ts +++ b/src/helpers/utils.ts @@ -200,3 +200,7 @@ export function toChecksumAddress(address: string) { return address; } } + +export function addressEqual(address1: string, address2: string) { + return address1.toLowerCase() === address2.toLowerCase(); +} diff --git a/src/plugins/oSnap/Create.vue b/src/plugins/oSnap/Create.vue index f4cc6fcc..d4942df8 100644 --- a/src/plugins/oSnap/Create.vue +++ b/src/plugins/oSnap/Create.vue @@ -49,19 +49,16 @@ const collectables = ref([]); function addTransaction(transaction: Transaction) { if (newPluginData.value.safe === null) return; newPluginData.value.safe.transactions.push(transaction); - update(newPluginData.value); } function removeTransaction(transactionIndex: number) { if (!newPluginData.value.safe) return; newPluginData.value.safe.transactions.splice(transactionIndex, 1); - update(newPluginData.value); } function updateTransaction(transaction: Transaction, transactionIndex: number) { if (!newPluginData.value.safe) return; newPluginData.value.safe.transactions[transactionIndex] = transaction; - update(newPluginData.value); } async function fetchTokens(url: string): Promise { diff --git a/src/plugins/oSnap/components/Input/FileInput/FileInput.vue b/src/plugins/oSnap/components/Input/FileInput/FileInput.vue new file mode 100644 index 00000000..2f86e80b --- /dev/null +++ b/src/plugins/oSnap/components/Input/FileInput/FileInput.vue @@ -0,0 +1,126 @@ + + + diff --git a/src/plugins/oSnap/components/Input/FileInput/utils.ts b/src/plugins/oSnap/components/Input/FileInput/utils.ts new file mode 100644 index 00000000..7716e49a --- /dev/null +++ b/src/plugins/oSnap/components/Input/FileInput/utils.ts @@ -0,0 +1,17 @@ +export function isFileOfType(file: File, type: File['type']) { + return file.type === type; +} + +export function getFilesFromEvent(event: DragEvent | Event) { + let _files: FileList | undefined | null; + + if (event instanceof DragEvent) { + _files = event.dataTransfer?.files; + } + + if (event.target && event.target instanceof HTMLInputElement) { + _files = (event?.currentTarget as HTMLInputElement)?.files; + } + if (!_files) return; + return _files; +} diff --git a/src/plugins/oSnap/components/Input/MethodParameter.vue b/src/plugins/oSnap/components/Input/MethodParameter.vue index a0f9025c..c14260d2 100644 --- a/src/plugins/oSnap/components/Input/MethodParameter.vue +++ b/src/plugins/oSnap/components/Input/MethodParameter.vue @@ -8,6 +8,7 @@ import { hexZeroPad, isBytesLike } from '@ethersproject/bytes'; const props = defineProps<{ parameter: ParamType; value: string; + validateOnMount?: boolean; }>(); const emit = defineEmits<{ @@ -37,8 +38,28 @@ const inputType = computed(() => { const label = `${props.parameter.name} (${props.parameter.type})`; const arrayPlaceholder = `E.g. ["text", 123, 0x123]`; +const newValue = ref(props.value); + +const validationState = ref(true); +const isInputValid = computed(() => validationState.value); + +const validationErrorMessage = ref(); +const errorMessageForDisplay = computed(() => { + if (!isInputValid.value) { + return validationErrorMessage.value + ? validationErrorMessage.value + : `Invalid ${props.parameter.baseType}`; + } +}); -const isInputValid = computed(() => { +const allowQuickFixForBytes32 = computed(() => { + if (!errorMessageForDisplay?.value?.includes('long')) { + return true; + } + return false; +}); + +function validate() { if (!isDirty.value) return true; if (isAddressInput.value) return isAddress(newValue.value); if (isArrayInput.value) return validateArrayInput(newValue.value); @@ -46,9 +67,7 @@ const isInputValid = computed(() => { if (isBytes32Input.value) return validateBytes32Input(newValue.value); if (isBytesInput.value) return validateBytesInput(newValue.value); return true; -}); - -const newValue = ref(props.value); +} watch(props.parameter, () => { newValue.value = ''; @@ -56,6 +75,11 @@ watch(props.parameter, () => { }); watch(newValue, () => { + const valid = validate(); + if (valid) { + validationErrorMessage.value = undefined; + } + validationState.value = valid; emit('updateParameterValue', newValue.value); }); @@ -67,12 +91,25 @@ function validateBytesInput(value: string) { return isBytesLike(value); } +// provide better feedback/validation messages for bytes32 inputs function validateBytes32Input(value: string) { try { - if (value.slice(2).length > 64) { - throw new Error('String too long'); + const data = value?.slice(2) || ''; + + if (data.length < 64) { + validationErrorMessage.value = 'Value too short'; + throw new Error('Less than 32 bytes'); + } + + if (data.length > 64) { + validationErrorMessage.value = 'Value too long'; + throw new Error('More than 32 bytes'); } - return isBytesLike(value); + + if (!isBytesLike(value)) { + throw new Error('Invalid bytes32'); + } + return true; } catch { return false; } @@ -103,6 +140,12 @@ function formatBytes32() { newValue.value = hexZeroPad(newValue.value, 32); } } +onMounted(() => { + if (props.validateOnMount) { + isDirty.value = true; + } + validationState.value = validate(); +});
- +
diff --git a/src/plugins/oSnap/components/TransactionBuilder/RawTransaction.vue b/src/plugins/oSnap/components/TransactionBuilder/RawTransaction.vue index 357f8783..19d58d5f 100644 --- a/src/plugins/oSnap/components/TransactionBuilder/RawTransaction.vue +++ b/src/plugins/oSnap/components/TransactionBuilder/RawTransaction.vue @@ -1,7 +1,5 @@ + + diff --git a/src/plugins/oSnap/components/TransactionBuilder/Transaction.vue b/src/plugins/oSnap/components/TransactionBuilder/Transaction.vue index e5251c02..a6185607 100644 --- a/src/plugins/oSnap/components/TransactionBuilder/Transaction.vue +++ b/src/plugins/oSnap/components/TransactionBuilder/Transaction.vue @@ -1,5 +1,4 @@