Skip to content

Commit

Permalink
Merge e5cc66a into 0e84f84
Browse files Browse the repository at this point in the history
  • Loading branch information
Uxio0 committed Jul 6, 2022
2 parents 0e84f84 + e5cc66a commit 0b3020b
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 60 deletions.
57 changes: 1 addition & 56 deletions gnosis/eth/django/filters.py
Original file line number Diff line number Diff line change
@@ -1,66 +1,11 @@
import binascii

from django.core.exceptions import ValidationError
from django.forms import CharField as CharFieldForm
from django.utils.translation import gettext_lazy as _

import django_filters
from hexbytes import HexBytes

from ..utils import fast_is_checksum_address


class EthereumAddressFieldForm(CharFieldForm):
default_error_messages = {
"invalid": _("Enter a valid checksummed Ethereum Address."),
}

def prepare_value(self, value):
return value

def to_python(self, value):
value = super().to_python(value)
if value in self.empty_values:
return None
elif not fast_is_checksum_address(value):
raise ValidationError(self.error_messages["invalid"], code="invalid")
return value
from .forms import EthereumAddressFieldForm, Keccak256FieldForm


class EthereumAddressFilter(django_filters.Filter):
field_class = EthereumAddressFieldForm


class Keccak256FieldForm(CharFieldForm):
default_error_messages = {
"invalid": _('"%(value)s" is not a valid keccak256 hash.'),
"length": _('"%(value)s" keccak256 hash should be 32 bytes.'),
}

def prepare_value(self, value):
return value

def to_python(self, value):
value = super().to_python(value)
if value in self.empty_values:
return None
else:
try:
bytes_value = HexBytes(value)
if len(bytes_value) != 32:
raise ValidationError(
self.error_messages["length"],
code="length",
params={"value": value},
)
except (binascii.Error, ValueError):
raise ValidationError(
self.error_messages["invalid"],
code="invalid",
params={"value": value},
)
return value


class Keccak256Filter(django_filters.Filter):
field_class = Keccak256FieldForm
74 changes: 74 additions & 0 deletions gnosis/eth/django/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import binascii

from django import forms
from django.core import exceptions
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _

from hexbytes import HexBytes

from gnosis.eth.utils import fast_is_checksum_address


class EthereumAddressFieldForm(forms.CharField):
default_error_messages = {
"invalid": _("Enter a valid checksummed Ethereum Address."),
}

def prepare_value(self, value):
return value

def to_python(self, value):
value = super().to_python(value)
if value in self.empty_values:
return None
elif not fast_is_checksum_address(value):
raise ValidationError(self.error_messages["invalid"], code="invalid")
return value


class HexFieldForm(forms.CharField):
default_error_messages = {
"invalid": _("Enter a valid hexadecimal."),
}

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.empty_value = None

def to_python(self, value: str) -> HexBytes:
value = value.strip()
if value in self.empty_values:
return self.empty_value
try:
return HexBytes(value)
except (binascii.Error, TypeError, ValueError):
raise exceptions.ValidationError(
self.error_messages["invalid"],
code="invalid",
params={"value": value},
)

def prepare_value(self, value: memoryview) -> str:
return "0x" + bytes(value).hex()


class Keccak256FieldForm(HexFieldForm):
default_error_messages = {
"invalid": _('"%(value)s" is not a valid keccak256 hash.'),
"length": _('"%(value)s" keccak256 hash should be 32 bytes.'),
}

def prepare_value(self, value: str) -> str:
# Keccak field already returns a hex str
return value

def to_python(self, value):
value = super().to_python(value)
if value and len(value) != 32:
raise ValidationError(
self.error_messages["length"],
code="length",
params={"value": value.hex()},
)
return value
13 changes: 11 additions & 2 deletions gnosis/eth/django/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from hexbytes import HexBytes

from ..utils import fast_bytes_to_checksum_address, fast_to_checksum_address
from .filters import EthereumAddressFieldForm, Keccak256FieldForm
from .forms import EthereumAddressFieldForm, HexFieldForm, Keccak256FieldForm
from .validators import validate_checksumed_address

try:
Expand Down Expand Up @@ -140,7 +140,7 @@ class HexField(models.CharField):
On Database side a CharField is used.
"""

description = "Stores a hex value into an CharField"
description = "Stores a hex value into an CharField. DEPRECATED, use a BinaryField"

def from_db_value(self, value, expression, connection):
return self.to_python(value)
Expand Down Expand Up @@ -177,6 +177,15 @@ def clean(self, value, model_instance):
return value


class HexV2Field(models.BinaryField):
def formfield(self, **kwargs):
defaults = {
"form_class": HexFieldForm,
}
defaults.update(kwargs)
return super().formfield(**defaults)


class Sha3HashField(HexField):
description = "DEPRECATED. Use `Keccak256Field`"

Expand Down
29 changes: 27 additions & 2 deletions gnosis/eth/django/tests/test_forms.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
from django.forms import forms
from django.test import TestCase

from hexbytes import HexBytes
from web3 import Web3

from ..filters import EthereumAddressFieldForm, Keccak256FieldForm
from ..forms import EthereumAddressFieldForm, HexFieldForm, Keccak256FieldForm


class EthereumAddressForm(forms.Form):
value = EthereumAddressFieldForm()


class HexForm(forms.Form):
value = HexFieldForm(required=False)


class Keccak256Form(forms.Form):
value = Keccak256FieldForm()
value = Keccak256FieldForm(required=False)


class TestForms(TestCase):
Expand All @@ -35,6 +40,22 @@ def test_ethereum_address_field_form(self):
)
self.assertTrue(form.is_valid())

def test_hex_field_form(self):
form = HexForm(data={"value": "not an hexadecimal"})
self.assertFalse(form.is_valid())
self.assertEqual(form.errors["value"], ["Enter a valid hexadecimal."])

form = HexForm(data={"value": "0xabcd"})
self.assertTrue(form.is_valid())
self.assertEqual(form.cleaned_data["value"], HexBytes("0xabcd"))

form = HexForm(initial={"value": memoryview(bytes.fromhex("cdef"))})
self.assertIn('value="0xcdef"', form.as_p())

form = HexForm(data={"value": ""})
self.assertTrue(form.is_valid())
self.assertIsNone(form.cleaned_data["value"])

def test_keccak256_field_form(self):
form = Keccak256Form(data={"value": "not a hash"})
self.assertFalse(form.is_valid())
Expand All @@ -50,3 +71,7 @@ def test_keccak256_field_form(self):

form = Keccak256Form(data={"value": Web3.keccak(text="testing").hex()})
self.assertTrue(form.is_valid())

form = Keccak256Form(data={"value": ""})
self.assertTrue(form.is_valid())
self.assertIsNone(form.cleaned_data["value"])

0 comments on commit 0b3020b

Please sign in to comment.